Changeset 779541b in mainline for uspace/lib/c/generic/inet/tcp.c
- Timestamp:
- 2015-05-09T13:43:50Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1d4b815
- Parents:
- 99ea91b2
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/inet/tcp.c
r99ea91b2 r779541b 30 30 * @{ 31 31 */ 32 /** @file UDP API32 /** @file TCP API 33 33 */ 34 34 … … 36 36 #include <inet/endpoint.h> 37 37 #include <inet/tcp.h> 38 #include <ipc/services.h> 39 #include <ipc/tcp.h> 40 #include <stdlib.h> 41 42 #include <stdio.h> 43 44 static void tcp_cb_conn(ipc_callid_t, ipc_call_t *, void *); 45 46 static int tcp_callback_create(tcp_t *tcp) 47 { 48 async_exch_t *exch = async_exchange_begin(tcp->sess); 49 50 printf("tcp_callback_create()\n"); 51 52 aid_t req = async_send_0(exch, TCP_CALLBACK_CREATE, NULL); 53 int rc = async_connect_to_me(exch, 0, 0, 0, tcp_cb_conn, tcp); 54 async_exchange_end(exch); 55 56 if (rc != EOK) 57 return rc; 58 59 sysarg_t retval; 60 async_wait_for(req, &retval); 61 62 return retval; 63 } 38 64 39 65 int tcp_create(tcp_t **rtcp) 40 66 { 41 return 0; 67 tcp_t *tcp; 68 service_id_t tcp_svcid; 69 int rc; 70 71 printf("tcp_create()\n"); 72 73 tcp = calloc(1, sizeof(tcp_t)); 74 if (tcp == NULL) { 75 rc = ENOMEM; 76 goto error; 77 } 78 79 list_initialize(&tcp->conn); 80 list_initialize(&tcp->listener); 81 82 rc = loc_service_get_id(SERVICE_NAME_TCP, &tcp_svcid, 83 IPC_FLAG_BLOCKING); 84 if (rc != EOK) { 85 rc = EIO; 86 goto error; 87 } 88 89 tcp->sess = loc_service_connect(EXCHANGE_SERIALIZE, tcp_svcid, 90 IPC_FLAG_BLOCKING); 91 if (tcp->sess == NULL) { 92 rc = EIO; 93 goto error; 94 } 95 96 rc = tcp_callback_create(tcp); 97 if (rc != EOK) { 98 rc = EIO; 99 goto error; 100 } 101 102 *rtcp = tcp; 103 return EOK; 104 error: 105 free(tcp); 106 return rc; 42 107 } 43 108 44 109 void tcp_destroy(tcp_t *tcp) 45 110 { 111 if (tcp == NULL) 112 return; 113 114 async_hangup(tcp->sess); 115 free(tcp); 46 116 } 47 117 … … 49 119 tcp_conn_t **rconn) 50 120 { 51 return 0; 121 async_exch_t *exch; 122 tcp_conn_t *conn; 123 ipc_call_t answer; 124 125 printf("tcp_conn_create()\n"); 126 127 conn = calloc(1, sizeof(tcp_conn_t)); 128 if (conn == NULL) 129 return ENOMEM; 130 131 conn->data_avail = false; 132 fibril_mutex_initialize(&conn->lock); 133 fibril_condvar_initialize(&conn->cv); 134 135 exch = async_exchange_begin(tcp->sess); 136 aid_t req = async_send_0(exch, TCP_CONN_CREATE, &answer); 137 sysarg_t rc = async_data_write_start(exch, (void *)epp, 138 sizeof(inet_ep2_t)); 139 async_exchange_end(exch); 140 141 if (rc != EOK) { 142 sysarg_t rc_orig; 143 async_wait_for(req, &rc_orig); 144 if (rc_orig != EOK) 145 rc = rc_orig; 146 goto error; 147 } 148 149 async_wait_for(req, &rc); 150 if (rc != EOK) 151 goto error; 152 153 conn->tcp = tcp; 154 conn->id = IPC_GET_ARG1(answer); 155 conn->cb = cb; 156 conn->cb_arg = arg; 157 158 list_append(&conn->ltcp, &tcp->conn); 159 *rconn = conn; 160 161 return EOK; 162 error: 163 free(conn); 164 return (int) rc; 52 165 } 53 166 54 167 void tcp_conn_destroy(tcp_conn_t *conn) 55 168 { 169 async_exch_t *exch; 170 171 printf("tcp_conn_destroy()\n"); 172 173 if (conn == NULL) 174 return; 175 176 list_remove(&conn->ltcp); 177 178 exch = async_exchange_begin(conn->tcp->sess); 179 sysarg_t rc = async_req_1_0(exch, TCP_CONN_DESTROY, conn->id); 180 async_exchange_end(exch); 181 182 free(conn); 183 (void) rc; 184 } 185 186 static int tcp_conn_get(tcp_t *tcp, sysarg_t id, tcp_conn_t **rconn) 187 { 188 list_foreach(tcp->conn, ltcp, tcp_conn_t, conn) { 189 if (conn->id == id) { 190 *rconn = conn; 191 return EOK; 192 } 193 } 194 195 return EINVAL; 56 196 } 57 197 58 198 void *tcp_conn_userptr(tcp_conn_t *conn) 59 199 { 60 return NULL;200 return conn->cb_arg; 61 201 } 62 202 … … 64 204 void *larg, tcp_cb_t *cb, void *arg, tcp_listener_t **rlst) 65 205 { 206 async_exch_t *exch; 207 tcp_listener_t *lst; 208 ipc_call_t answer; 209 210 printf("tcp_listener_create()\n"); 211 212 lst = calloc(1, sizeof(tcp_listener_t)); 213 if (lst == NULL) 214 return ENOMEM; 215 216 exch = async_exchange_begin(tcp->sess); 217 aid_t req = async_send_0(exch, TCP_LISTENER_CREATE, &answer); 218 sysarg_t rc = async_data_write_start(exch, (void *)ep, 219 sizeof(inet_ep_t)); 220 async_exchange_end(exch); 221 222 if (rc != EOK) { 223 sysarg_t rc_orig; 224 async_wait_for(req, &rc_orig); 225 if (rc_orig != EOK) 226 rc = rc_orig; 227 goto error; 228 } 229 230 async_wait_for(req, &rc); 231 if (rc != EOK) 232 goto error; 233 234 lst->tcp = tcp; 235 lst->id = IPC_GET_ARG1(answer); 236 lst->lcb = lcb; 237 lst->lcb_arg = larg; 238 lst->cb = cb; 239 lst->cb_arg = arg; 240 241 list_append(&lst->ltcp, &tcp->listener); 242 *rlst = lst; 243 244 return EOK; 245 error: 246 free(lst); 247 return (int) rc; 248 } 249 250 void tcp_listener_destroy(tcp_listener_t *lst) 251 { 252 async_exch_t *exch; 253 254 printf("tcp_listener_destroy()\n"); 255 256 if (lst == NULL) 257 return; 258 259 list_remove(&lst->ltcp); 260 261 exch = async_exchange_begin(lst->tcp->sess); 262 sysarg_t rc = async_req_1_0(exch, TCP_LISTENER_DESTROY, lst->id); 263 async_exchange_end(exch); 264 265 free(lst); 266 (void) rc; 267 } 268 269 void *tcp_listener_userptr(tcp_listener_t *lst) 270 { 271 return lst->lcb_arg; 272 } 273 274 int tcp_conn_wait_connected(tcp_conn_t *conn) 275 { 276 async_usleep(1000 * 1000); 66 277 return 0; 67 278 } 68 279 69 void tcp_listener_destroy(tcp_listener_t *lst)70 {71 }72 73 void *tcp_listener_userptr(tcp_listener_t *lst)74 {75 return NULL;76 }77 78 79 int tcp_conn_wait_connected(tcp_conn_t *conn)80 {81 return 0;82 }83 84 280 int tcp_conn_send(tcp_conn_t *conn, const void *data, size_t bytes) 85 281 { 86 return 0; 87 } 282 async_exch_t *exch; 283 sysarg_t rc; 284 285 printf("tcp_conn_send()\n"); 286 287 exch = async_exchange_begin(conn->tcp->sess); 288 aid_t req = async_send_1(exch, TCP_CONN_SEND, conn->id, NULL); 289 290 rc = async_data_write_start(exch, data, bytes); 291 if (rc != EOK) { 292 async_forget(req); 293 return rc; 294 } 295 296 async_exchange_end(exch); 297 298 if (rc != EOK) { 299 async_forget(req); 300 return rc; 301 } 302 303 async_wait_for(req, &rc); 304 return rc; 305 } 306 88 307 89 308 int tcp_conn_send_fin(tcp_conn_t *conn) 90 309 { 91 return 0; 310 async_exch_t *exch; 311 312 printf("tcp_conn_send_fin()\n"); 313 314 exch = async_exchange_begin(conn->tcp->sess); 315 sysarg_t rc = async_req_1_0(exch, TCP_CONN_SEND_FIN, conn->id); 316 async_exchange_end(exch); 317 318 return rc; 92 319 } 93 320 94 321 int tcp_conn_push(tcp_conn_t *conn) 95 322 { 96 return 0; 97 } 98 99 void tcp_conn_reset(tcp_conn_t *conn) 100 { 101 } 102 323 async_exch_t *exch; 324 325 printf("tcp_conn_push()\n"); 326 327 exch = async_exchange_begin(conn->tcp->sess); 328 sysarg_t rc = async_req_1_0(exch, TCP_CONN_PUSH, conn->id); 329 async_exchange_end(exch); 330 331 return rc; 332 } 333 334 int tcp_conn_reset(tcp_conn_t *conn) 335 { 336 async_exch_t *exch; 337 338 printf("tcp_conn_reset()\n"); 339 340 exch = async_exchange_begin(conn->tcp->sess); 341 sysarg_t rc = async_req_1_0(exch, TCP_CONN_RESET, conn->id); 342 async_exchange_end(exch); 343 344 return rc; 345 } 103 346 104 347 int tcp_conn_recv(tcp_conn_t *conn, void *buf, size_t bsize, size_t *nrecv) 105 348 { 106 return 0; 349 async_exch_t *exch; 350 ipc_call_t answer; 351 352 printf("tcp_conn_recv() bsize=%zu\n", bsize); 353 354 fibril_mutex_lock(&conn->lock); 355 if (!conn->data_avail) { 356 printf("returning EAGAIN\n"); 357 fibril_mutex_unlock(&conn->lock); 358 return EAGAIN; 359 } 360 361 exch = async_exchange_begin(conn->tcp->sess); 362 aid_t req = async_send_1(exch, TCP_CONN_RECV, conn->id, &answer); 363 int rc = async_data_read_start(exch, buf, bsize); 364 async_exchange_end(exch); 365 366 if (rc != EOK) { 367 printf("got rc = %d\n", rc); 368 async_forget(req); 369 fibril_mutex_unlock(&conn->lock); 370 return rc; 371 } 372 373 sysarg_t retval; 374 async_wait_for(req, &retval); 375 if (retval != EOK) { 376 printf("got rc = %d\n", rc); 377 fibril_mutex_unlock(&conn->lock); 378 return retval; 379 } 380 381 *nrecv = IPC_GET_ARG1(answer); 382 fibril_mutex_unlock(&conn->lock); 383 return EOK; 107 384 } 108 385 109 386 int tcp_conn_recv_wait(tcp_conn_t *conn, void *buf, size_t bsize, size_t *nrecv) 110 387 { 111 return 0; 388 async_exch_t *exch; 389 ipc_call_t answer; 390 391 printf("tcp_conn_recv_wait() bsize=%zu\n", bsize); 392 again: 393 fibril_mutex_lock(&conn->lock); 394 while (!conn->data_avail) { 395 printf("wait for data to be avail\n"); 396 fibril_condvar_wait(&conn->cv, &conn->lock); 397 } 398 399 printf("tcp_conn_recv_wait - get data\n"); 400 exch = async_exchange_begin(conn->tcp->sess); 401 aid_t req = async_send_1(exch, TCP_CONN_RECV_WAIT, conn->id, &answer); 402 int rc = async_data_read_start(exch, buf, bsize); 403 printf("tcp_conn_recv_wait - rc = %d\n", rc); 404 async_exchange_end(exch); 405 406 if (rc != EOK) { 407 printf("got rc=%d\n", rc); 408 async_forget(req); 409 if (rc == EAGAIN) { 410 conn->data_avail = false; 411 fibril_mutex_unlock(&conn->lock); 412 goto again; 413 } 414 fibril_mutex_unlock(&conn->lock); 415 return rc; 416 } 417 418 sysarg_t retval; 419 async_wait_for(req, &retval); 420 if (retval != EOK) { 421 printf("got retval != EOK\n"); 422 if (rc == EAGAIN) { 423 printf("rc == EAGAIN\n"); 424 conn->data_avail = false; 425 } 426 fibril_mutex_unlock(&conn->lock); 427 return retval; 428 } 429 430 *nrecv = IPC_GET_ARG1(answer); 431 fibril_mutex_unlock(&conn->lock); 432 printf("tcp_conn_recv_wait: nrecv=%zu\n", *nrecv); 433 printf("received: '"); 434 size_t i; 435 for (i = 0; i < *nrecv; i++) { 436 putchar((char)((char *)buf)[i]); 437 } 438 printf("'\n"); 439 return EOK; 440 } 441 442 static void tcp_ev_connected(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall) 443 { 444 printf("tcp_ev_connected()\n"); 445 async_answer_0(iid, ENOTSUP); 446 } 447 448 static void tcp_ev_conn_failed(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall) 449 { 450 printf("tcp_ev_conn_failed()\n"); 451 async_answer_0(iid, ENOTSUP); 452 } 453 454 static void tcp_ev_conn_reset(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall) 455 { 456 printf("tcp_ev_conn_reset()\n"); 457 async_answer_0(iid, ENOTSUP); 458 } 459 460 static void tcp_ev_data(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall) 461 { 462 tcp_conn_t *conn; 463 sysarg_t conn_id; 464 int rc; 465 466 printf("tcp_ev_data()\n"); 467 conn_id = IPC_GET_ARG1(*icall); 468 469 rc = tcp_conn_get(tcp, conn_id, &conn); 470 if (rc != EOK) { 471 printf("conn ID %zu not found\n", 472 conn_id); 473 async_answer_0(iid, ENOENT); 474 return; 475 } 476 477 conn->data_avail = true; 478 fibril_condvar_broadcast(&conn->cv); 479 480 async_answer_0(iid, EOK); 481 } 482 483 static void tcp_ev_urg_data(tcp_t *tcp, ipc_callid_t iid, ipc_call_t *icall) 484 { 485 printf("tcp_ev_urg_data()\n"); 486 async_answer_0(iid, ENOTSUP); 487 } 488 489 static void tcp_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) 490 { 491 tcp_t *tcp = (tcp_t *)arg; 492 493 async_answer_0(iid, EOK); 494 495 printf("tcp_cb_conn()\n"); 496 497 while (true) { 498 ipc_call_t call; 499 ipc_callid_t callid = async_get_call(&call); 500 501 printf("tcp_cb_conn() - msg %d\n", 502 (int)IPC_GET_IMETHOD(call)); 503 if (!IPC_GET_IMETHOD(call)) { 504 /* TODO: Handle hangup */ 505 return; 506 } 507 508 switch (IPC_GET_IMETHOD(call)) { 509 case TCP_EV_CONNECTED: 510 tcp_ev_connected(tcp, callid, &call); 511 break; 512 case TCP_EV_CONN_FAILED: 513 tcp_ev_conn_failed(tcp, callid, &call); 514 break; 515 case TCP_EV_CONN_RESET: 516 tcp_ev_conn_reset(tcp, callid, &call); 517 break; 518 case TCP_EV_DATA: 519 tcp_ev_data(tcp, callid, &call); 520 break; 521 case TCP_EV_URG_DATA: 522 tcp_ev_urg_data(tcp, callid, &call); 523 break; 524 default: 525 async_answer_0(callid, ENOTSUP); 526 break; 527 } 528 } 112 529 } 113 530
Note:
See TracChangeset
for help on using the changeset viewer.