Changeset 48171fc4 in mainline for uspace/srv/net/dnsrsrv/transport.c
- Timestamp:
- 2013-05-03T08:10:02Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a0d97f83
- Parents:
- fff7ef4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/dnsrsrv/transport.c
rfff7ef4 r48171fc4 34 34 */ 35 35 36 #include <adt/list.h> 36 37 #include <errno.h> 38 #include <fibril_synch.h> 39 #include <io/log.h> 37 40 #include <net/in.h> 38 41 #include <net/inet.h> 39 42 #include <net/socket.h> 43 #include <stdbool.h> 40 44 #include <stdlib.h> 41 45 … … 44 48 #include "transport.h" 45 49 46 #include <stdio.h>47 48 50 #define RECV_BUF_SIZE 4096 49 51 52 /** Request timeout (microseconds) */ 53 #define REQ_TIMEOUT (5*1000*1000) 54 55 typedef struct { 56 link_t lreq; 57 dns_message_t *req; 58 dns_message_t *resp; 59 60 bool done; 61 fibril_condvar_t done_cv; 62 fibril_mutex_t done_lock; 63 64 int status; 65 } trans_req_t; 66 50 67 static uint8_t recv_buf[RECV_BUF_SIZE]; 68 static fid_t recv_fid; 69 static int transport_fd = -1; 70 71 /** Outstanding requests */ 72 static LIST_INITIALIZE(treq_list); 73 static FIBRIL_MUTEX_INITIALIZE(treq_lock); 74 75 static int transport_recv_fibril(void *arg); 76 77 int transport_init(void) 78 { 79 struct sockaddr_in laddr; 80 int fd; 81 fid_t fid; 82 int rc; 83 84 laddr.sin_family = AF_INET; 85 laddr.sin_port = htons(12345); 86 laddr.sin_addr.s_addr = INADDR_ANY; 87 88 fd = -1; 89 90 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 91 if (fd < 0) { 92 rc = EIO; 93 goto error; 94 } 95 96 rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); 97 if (rc != EOK) 98 goto error; 99 100 transport_fd = fd; 101 102 fid = fibril_create(transport_recv_fibril, NULL); 103 if (fid == 0) 104 goto error; 105 106 fibril_add_ready(fid); 107 recv_fid = fid; 108 return EOK; 109 error: 110 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing network socket.\n"); 111 if (fd >= 0) 112 closesocket(fd); 113 return rc; 114 } 115 116 void transport_fini(void) 117 { 118 if (transport_fd >= 0) 119 closesocket(transport_fd); 120 } 121 122 static trans_req_t *treq_create(dns_message_t *req) 123 { 124 trans_req_t *treq; 125 126 treq = calloc(1, sizeof(trans_req_t)); 127 if (treq == NULL) 128 return NULL; 129 130 treq->req = req; 131 treq->resp = NULL; 132 treq->done = false; 133 fibril_condvar_initialize(&treq->done_cv); 134 fibril_mutex_initialize(&treq->done_lock); 135 136 fibril_mutex_lock(&treq_lock); 137 list_append(&treq->lreq, &treq_list); 138 fibril_mutex_unlock(&treq_lock); 139 140 return treq; 141 } 142 143 static void treq_destroy(trans_req_t *treq) 144 { 145 if (link_in_use(&treq->lreq)) 146 list_remove(&treq->lreq); 147 free(treq); 148 } 149 150 static trans_req_t *treq_match_resp(dns_message_t *resp) 151 { 152 assert(fibril_mutex_is_locked(&treq_lock)); 153 154 list_foreach(treq_list, link) { 155 trans_req_t *treq = list_get_instance(link, trans_req_t, lreq); 156 157 if (treq->req->id == resp->id) { 158 /* Match */ 159 return treq; 160 } 161 } 162 163 return NULL; 164 } 165 166 static void treq_complete(trans_req_t *treq, dns_message_t *resp) 167 { 168 fibril_mutex_lock(&treq->done_lock); 169 treq->done = true; 170 treq->status = EOK; 171 treq->resp = resp; 172 fibril_mutex_unlock(&treq->done_lock); 173 174 fibril_condvar_broadcast(&treq->done_cv); 175 } 51 176 52 177 int dns_request(dns_message_t *req, dns_message_t **rresp) 53 178 { 54 dns_message_t *resp;55 179 int rc; 56 180 void *req_data; 57 181 size_t req_size; 58 182 struct sockaddr_in addr; 59 struct sockaddr_in laddr; 183 trans_req_t *treq; 184 185 req_data = NULL; 186 treq = NULL; 187 188 addr.sin_family = AF_INET; 189 addr.sin_port = htons(53); 190 addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138); 191 192 rc = dns_message_encode(req, &req_data, &req_size); 193 if (rc != EOK) 194 goto error; 195 196 rc = sendto(transport_fd, req_data, req_size, 0, 197 (struct sockaddr *)&addr, sizeof(addr)); 198 if (rc != EOK) 199 goto error; 200 201 treq = treq_create(req); 202 if (treq == NULL) { 203 rc = ENOMEM; 204 goto error; 205 } 206 207 fibril_mutex_lock(&treq->done_lock); 208 while (treq->done != true) { 209 rc = fibril_condvar_wait_timeout(&treq->done_cv, &treq->done_lock, 210 REQ_TIMEOUT); 211 if (rc == ETIMEOUT) { 212 fibril_mutex_unlock(&treq->done_lock); 213 rc = EIO; 214 goto error; 215 } 216 } 217 218 fibril_mutex_unlock(&treq->done_lock); 219 220 if (treq->status != EOK) { 221 rc = treq->status; 222 goto error; 223 } 224 225 *rresp = treq->resp; 226 treq_destroy(treq); 227 free(req_data); 228 return EOK; 229 error: 230 if (treq != NULL) 231 treq_destroy(treq); 232 free(req_data); 233 return rc; 234 } 235 236 static int transport_recv_msg(dns_message_t **rresp) 237 { 60 238 struct sockaddr_in src_addr; 61 239 socklen_t src_addr_size; 62 240 size_t recv_size; 63 int fd; 64 int i; 65 66 addr.sin_family = AF_INET; 67 addr.sin_port = htons(53); 68 addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138); 69 70 laddr.sin_family = AF_INET; 71 laddr.sin_port = htons(12345); 72 laddr.sin_addr.s_addr = INADDR_ANY; 73 74 req_data = NULL; 75 fd = -1; 76 77 rc = dns_message_encode(req, &req_data, &req_size); 78 if (rc != EOK) 79 goto error; 80 81 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 82 if (fd < 0) { 83 rc = EIO; 84 goto error; 85 } 86 87 rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); 88 if (rc != EOK) 89 goto error; 90 91 printf("fd=%d req_data=%p, req_size=%zu\n", fd, req_data, req_size); 92 rc = sendto(fd, req_data, req_size, 0, (struct sockaddr *)&addr, 93 sizeof(addr)); 94 if (rc != EOK) 95 goto error; 241 dns_message_t *resp; 242 int rc; 96 243 97 244 src_addr_size = sizeof(src_addr); 98 rc = recvfrom( fd, recv_buf, RECV_BUF_SIZE, 0,245 rc = recvfrom(transport_fd, recv_buf, RECV_BUF_SIZE, 0, 99 246 (struct sockaddr *)&src_addr, &src_addr_size); 100 247 if (rc < 0) { 101 printf("recvfrom returns error - %d\n", rc);248 log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom returns error - %d\n", rc); 102 249 goto error; 103 250 } 104 251 105 252 recv_size = (size_t)rc; 106 107 printf("received %d bytes\n", (int)recv_size);108 for (i = 0; i < (int)recv_size; i++) {109 if (recv_buf[i] >= 32 && recv_buf[i] < 127)110 printf("%c", recv_buf[i]);111 else112 printf("?");113 }114 printf("\n");115 116 printf("close socket\n");117 closesocket(fd);118 printf("free req_data\n");119 free(req_data);120 253 121 254 rc = dns_message_decode(recv_buf, recv_size, &resp); … … 129 262 130 263 error: 131 if (req_data != NULL)132 free(req_data);133 if (fd >= 0)134 closesocket(fd);135 264 return rc; 136 265 } 137 266 267 static int transport_recv_fibril(void *arg) 268 { 269 dns_message_t *resp; 270 trans_req_t *treq; 271 int rc; 272 273 while (true) { 274 rc = transport_recv_msg(&resp); 275 if (rc != EOK) 276 continue; 277 278 fibril_mutex_lock(&treq_lock); 279 treq = treq_match_resp(resp); 280 if (treq == NULL) { 281 fibril_mutex_unlock(&treq_lock); 282 continue; 283 } 284 285 list_remove(&treq->lreq); 286 fibril_mutex_unlock(&treq_lock); 287 288 treq_complete(treq, resp); 289 } 290 291 return 0; 292 } 293 138 294 /** @} 139 295 */
Note:
See TracChangeset
for help on using the changeset viewer.