00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "lwip/opt.h"
00040
00041 #if LWIP_NETCONN
00042
00043 #include "lwip/api_msg.h"
00044
00045 #include "lwip/ip.h"
00046 #include "lwip/udp.h"
00047 #include "lwip/tcp.h"
00048 #include "lwip/raw.h"
00049
00050 #include "lwip/memp.h"
00051 #include "lwip/tcpip.h"
00052 #include "lwip/igmp.h"
00053 #include "lwip/dns.h"
00054
00055 #include <string.h>
00056
00057 #define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \
00058 (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
00059 } else { \
00060 (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0)
00061 #define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
00062
00063
00064 #if LWIP_TCP
00065 static err_t do_writemore(struct netconn *conn);
00066 static void do_close_internal(struct netconn *conn);
00067 #endif
00068
00069 #if LWIP_RAW
00070
00071
00072
00073
00074
00075
00076
00077 static u8_t
00078 recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
00079 ip_addr_t *addr)
00080 {
00081 struct pbuf *q;
00082 struct netbuf *buf;
00083 struct netconn *conn;
00084
00085 LWIP_UNUSED_ARG(addr);
00086 conn = (struct netconn *)arg;
00087
00088 if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) {
00089 #if LWIP_SO_RCVBUF
00090 int recv_avail;
00091 SYS_ARCH_GET(conn->recv_avail, recv_avail);
00092 if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) {
00093 return 0;
00094 }
00095 #endif
00096
00097 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
00098 if(q != NULL) {
00099 if (pbuf_copy(q, p) != ERR_OK) {
00100 pbuf_free(q);
00101 q = NULL;
00102 }
00103 }
00104
00105 if (q != NULL) {
00106 u16_t len;
00107 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
00108 if (buf == NULL) {
00109 pbuf_free(q);
00110 return 0;
00111 }
00112
00113 buf->p = q;
00114 buf->ptr = q;
00115 ip_addr_copy(buf->addr, *ip_current_src_addr());
00116 buf->port = pcb->protocol;
00117
00118 len = q->tot_len;
00119 if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
00120 netbuf_delete(buf);
00121 return 0;
00122 } else {
00123 #if LWIP_SO_RCVBUF
00124 SYS_ARCH_INC(conn->recv_avail, len);
00125 #endif
00126
00127 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
00128 }
00129 }
00130 }
00131
00132 return 0;
00133 }
00134 #endif
00135
00136 #if LWIP_UDP
00137
00138
00139
00140
00141
00142
00143 static void
00144 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
00145 ip_addr_t *addr, u16_t port)
00146 {
00147 struct netbuf *buf;
00148 struct netconn *conn;
00149 u16_t len;
00150 #if LWIP_SO_RCVBUF
00151 int recv_avail;
00152 #endif
00153
00154 LWIP_UNUSED_ARG(pcb);
00155 LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
00156 LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
00157 conn = (struct netconn *)arg;
00158 LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
00159
00160 #if LWIP_SO_RCVBUF
00161 SYS_ARCH_GET(conn->recv_avail, recv_avail);
00162 if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
00163 ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
00164 #else
00165 if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
00166 #endif
00167 pbuf_free(p);
00168 return;
00169 }
00170
00171 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
00172 if (buf == NULL) {
00173 pbuf_free(p);
00174 return;
00175 } else {
00176 buf->p = p;
00177 buf->ptr = p;
00178 ip_addr_set(&buf->addr, addr);
00179 buf->port = port;
00180 #if LWIP_NETBUF_RECVINFO
00181 {
00182 const struct ip_hdr* iphdr = ip_current_header();
00183
00184 const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
00185 #if LWIP_CHECKSUM_ON_COPY
00186 buf->flags = NETBUF_FLAG_DESTADDR;
00187 #endif
00188 ip_addr_set(&buf->toaddr, ip_current_dest_addr());
00189 buf->toport_chksum = udphdr->dest;
00190 }
00191 #endif
00192 }
00193
00194 len = p->tot_len;
00195 if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
00196 netbuf_delete(buf);
00197 return;
00198 } else {
00199 #if LWIP_SO_RCVBUF
00200 SYS_ARCH_INC(conn->recv_avail, len);
00201 #endif
00202
00203 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
00204 }
00205 }
00206 #endif
00207
00208 #if LWIP_TCP
00209
00210
00211
00212
00213
00214
00215 static err_t
00216 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
00217 {
00218 struct netconn *conn;
00219 u16_t len;
00220
00221 LWIP_UNUSED_ARG(pcb);
00222 LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
00223 LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
00224 conn = (struct netconn *)arg;
00225 LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
00226
00227 if (conn == NULL) {
00228 return ERR_VAL;
00229 }
00230 if (!sys_mbox_valid(&conn->recvmbox)) {
00231
00232 if (p != NULL) {
00233 tcp_recved(pcb, p->tot_len);
00234 pbuf_free(p);
00235 }
00236 return ERR_OK;
00237 }
00238
00239
00240
00241
00242
00243 NETCONN_SET_SAFE_ERR(conn, err);
00244
00245 if (p != NULL) {
00246 len = p->tot_len;
00247 } else {
00248 len = 0;
00249 }
00250
00251 if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
00252
00253 return ERR_MEM;
00254 } else {
00255 #if LWIP_SO_RCVBUF
00256 SYS_ARCH_INC(conn->recv_avail, len);
00257 #endif
00258
00259 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
00260 }
00261
00262 return ERR_OK;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 static err_t
00277 poll_tcp(void *arg, struct tcp_pcb *pcb)
00278 {
00279 struct netconn *conn = (struct netconn *)arg;
00280
00281 LWIP_UNUSED_ARG(pcb);
00282 LWIP_ASSERT("conn != NULL", (conn != NULL));
00283
00284 if (conn->state == NETCONN_WRITE) {
00285 do_writemore(conn);
00286 } else if (conn->state == NETCONN_CLOSE) {
00287 do_close_internal(conn);
00288 }
00289
00290
00291
00292 if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
00293
00294
00295 if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
00296 (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
00297 conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
00298 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
00299 }
00300 }
00301
00302 return ERR_OK;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312 static err_t
00313 sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
00314 {
00315 struct netconn *conn = (struct netconn *)arg;
00316
00317 LWIP_UNUSED_ARG(pcb);
00318 LWIP_ASSERT("conn != NULL", (conn != NULL));
00319
00320 if (conn->state == NETCONN_WRITE) {
00321 do_writemore(conn);
00322 } else if (conn->state == NETCONN_CLOSE) {
00323 do_close_internal(conn);
00324 }
00325
00326 if (conn) {
00327
00328
00329 if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
00330 (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
00331 conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
00332 API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
00333 }
00334 }
00335
00336 return ERR_OK;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 static void
00347 err_tcp(void *arg, err_t err)
00348 {
00349 struct netconn *conn;
00350 enum netconn_state old_state;
00351 SYS_ARCH_DECL_PROTECT(lev);
00352
00353 conn = (struct netconn *)arg;
00354 LWIP_ASSERT("conn != NULL", (conn != NULL));
00355
00356 conn->pcb.tcp = NULL;
00357
00358
00359 SYS_ARCH_PROTECT(lev);
00360 conn->last_err = err;
00361 SYS_ARCH_UNPROTECT(lev);
00362
00363
00364 old_state = conn->state;
00365 conn->state = NETCONN_NONE;
00366
00367
00368
00369 API_EVENT(conn, NETCONN_EVT_ERROR, 0);
00370
00371
00372 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
00373 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
00374
00375
00376 if (sys_mbox_valid(&conn->recvmbox)) {
00377
00378 sys_mbox_trypost(&conn->recvmbox, NULL);
00379 }
00380
00381 if (sys_mbox_valid(&conn->acceptmbox)) {
00382
00383 sys_mbox_trypost(&conn->acceptmbox, NULL);
00384 }
00385
00386 if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
00387 (old_state == NETCONN_CONNECT)) {
00388
00389
00390 int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
00391 SET_NONBLOCKING_CONNECT(conn, 0);
00392
00393 if (!was_nonblocking_connect) {
00394
00395 LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
00396 conn->current_msg->err = err;
00397 conn->current_msg = NULL;
00398
00399 sys_sem_signal(&conn->op_completed);
00400 }
00401 } else {
00402 LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411
00412 static void
00413 setup_tcp(struct netconn *conn)
00414 {
00415 struct tcp_pcb *pcb;
00416
00417 pcb = conn->pcb.tcp;
00418 tcp_arg(pcb, conn);
00419 tcp_recv(pcb, recv_tcp);
00420 tcp_sent(pcb, sent_tcp);
00421 tcp_poll(pcb, poll_tcp, 4);
00422 tcp_err(pcb, err_tcp);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431 static err_t
00432 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
00433 {
00434 struct netconn *newconn;
00435 struct netconn *conn = (struct netconn *)arg;
00436
00437 LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
00438
00439 if (!sys_mbox_valid(&conn->acceptmbox)) {
00440 LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
00441 return ERR_VAL;
00442 }
00443
00444
00445
00446 newconn = netconn_alloc(conn->type, conn->callback);
00447 if (newconn == NULL) {
00448 return ERR_MEM;
00449 }
00450 newconn->pcb.tcp = newpcb;
00451 setup_tcp(newconn);
00452
00453
00454 newconn->last_err = err;
00455
00456 if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
00457
00458
00459
00460 struct tcp_pcb* pcb = newconn->pcb.tcp;
00461 tcp_arg(pcb, NULL);
00462 tcp_recv(pcb, NULL);
00463 tcp_sent(pcb, NULL);
00464 tcp_poll(pcb, NULL, 4);
00465 tcp_err(pcb, NULL);
00466
00467 newconn->pcb.tcp = NULL;
00468
00469 sys_mbox_free(&newconn->recvmbox);
00470 sys_mbox_set_invalid(&newconn->recvmbox);
00471 netconn_free(newconn);
00472 return ERR_MEM;
00473 } else {
00474
00475 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
00476 }
00477
00478 return ERR_OK;
00479 }
00480 #endif
00481
00482
00483
00484
00485
00486
00487
00488
00489 static void
00490 pcb_new(struct api_msg_msg *msg)
00491 {
00492 LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
00493
00494
00495 switch(NETCONNTYPE_GROUP(msg->conn->type)) {
00496 #if LWIP_RAW
00497 case NETCONN_RAW:
00498 msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
00499 if(msg->conn->pcb.raw == NULL) {
00500 msg->err = ERR_MEM;
00501 break;
00502 }
00503 raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
00504 break;
00505 #endif
00506 #if LWIP_UDP
00507 case NETCONN_UDP:
00508 msg->conn->pcb.udp = udp_new();
00509 if(msg->conn->pcb.udp == NULL) {
00510 msg->err = ERR_MEM;
00511 break;
00512 }
00513 #if LWIP_UDPLITE
00514 if (msg->conn->type==NETCONN_UDPLITE) {
00515 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
00516 }
00517 #endif
00518 if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
00519 udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
00520 }
00521 udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
00522 break;
00523 #endif
00524 #if LWIP_TCP
00525 case NETCONN_TCP:
00526 msg->conn->pcb.tcp = tcp_new();
00527 if(msg->conn->pcb.tcp == NULL) {
00528 msg->err = ERR_MEM;
00529 break;
00530 }
00531 setup_tcp(msg->conn);
00532 break;
00533 #endif
00534 default:
00535
00536 msg->err = ERR_VAL;
00537 break;
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 void
00548 do_newconn(struct api_msg_msg *msg)
00549 {
00550 msg->err = ERR_OK;
00551 if(msg->conn->pcb.tcp == NULL) {
00552 pcb_new(msg);
00553 }
00554
00555
00556
00557
00558 TCPIP_APIMSG_ACK(msg);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 struct netconn*
00572 netconn_alloc(enum netconn_type t, netconn_callback callback)
00573 {
00574 struct netconn *conn;
00575 int size;
00576
00577 conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
00578 if (conn == NULL) {
00579 return NULL;
00580 }
00581
00582 conn->last_err = ERR_OK;
00583 conn->type = t;
00584 conn->pcb.tcp = NULL;
00585
00586 #if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \
00587 (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE)
00588 size = DEFAULT_RAW_RECVMBOX_SIZE;
00589 #else
00590 switch(NETCONNTYPE_GROUP(t)) {
00591 #if LWIP_RAW
00592 case NETCONN_RAW:
00593 size = DEFAULT_RAW_RECVMBOX_SIZE;
00594 break;
00595 #endif
00596 #if LWIP_UDP
00597 case NETCONN_UDP:
00598 size = DEFAULT_UDP_RECVMBOX_SIZE;
00599 break;
00600 #endif
00601 #if LWIP_TCP
00602 case NETCONN_TCP:
00603 size = DEFAULT_TCP_RECVMBOX_SIZE;
00604 break;
00605 #endif
00606 default:
00607 LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);
00608 goto free_and_return;
00609 }
00610 #endif
00611
00612 if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
00613 goto free_and_return;
00614 }
00615 if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
00616 sys_sem_free(&conn->op_completed);
00617 goto free_and_return;
00618 }
00619
00620 #if LWIP_TCP
00621 sys_mbox_set_invalid(&conn->acceptmbox);
00622 #endif
00623 conn->state = NETCONN_NONE;
00624 #if LWIP_SOCKET
00625
00626 conn->socket = -1;
00627 #endif
00628 conn->callback = callback;
00629 #if LWIP_TCP
00630 conn->current_msg = NULL;
00631 conn->write_offset = 0;
00632 #endif
00633 #if LWIP_SO_SNDTIMEO
00634 conn->send_timeout = 0;
00635 #endif
00636 #if LWIP_SO_RCVTIMEO
00637 conn->recv_timeout = 0;
00638 #endif
00639 #if LWIP_SO_RCVBUF
00640 conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
00641 conn->recv_avail = 0;
00642 #endif
00643 conn->flags = 0;
00644 return conn;
00645 free_and_return:
00646 memp_free(MEMP_NETCONN, conn);
00647 return NULL;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 void
00657 netconn_free(struct netconn *conn)
00658 {
00659 LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
00660 LWIP_ASSERT("recvmbox must be deallocated before calling this function",
00661 !sys_mbox_valid(&conn->recvmbox));
00662 #if LWIP_TCP
00663 LWIP_ASSERT("acceptmbox must be deallocated before calling this function",
00664 !sys_mbox_valid(&conn->acceptmbox));
00665 #endif
00666
00667 sys_sem_free(&conn->op_completed);
00668 sys_sem_set_invalid(&conn->op_completed);
00669
00670 memp_free(MEMP_NETCONN, conn);
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 static void
00682 netconn_drain(struct netconn *conn)
00683 {
00684 void *mem;
00685 #if LWIP_TCP
00686 struct pbuf *p;
00687 #endif
00688
00689
00690
00691
00692 if (sys_mbox_valid(&conn->recvmbox)) {
00693 while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
00694 #if LWIP_TCP
00695 if (conn->type == NETCONN_TCP) {
00696 if(mem != NULL) {
00697 p = (struct pbuf*)mem;
00698
00699 if (conn->pcb.tcp != NULL) {
00700 tcp_recved(conn->pcb.tcp, p->tot_len);
00701 }
00702 pbuf_free(p);
00703 }
00704 } else
00705 #endif
00706 {
00707 netbuf_delete((struct netbuf *)mem);
00708 }
00709 }
00710 sys_mbox_free(&conn->recvmbox);
00711 sys_mbox_set_invalid(&conn->recvmbox);
00712 }
00713
00714
00715 #if LWIP_TCP
00716 if (sys_mbox_valid(&conn->acceptmbox)) {
00717 while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
00718 struct netconn *newconn = (struct netconn *)mem;
00719
00720
00721 if (conn->pcb.tcp != NULL) {
00722 tcp_accepted(conn->pcb.tcp);
00723 }
00724
00725 netconn_drain(newconn);
00726 if (newconn->pcb.tcp != NULL) {
00727 tcp_abort(newconn->pcb.tcp);
00728 newconn->pcb.tcp = NULL;
00729 }
00730 netconn_free(newconn);
00731 }
00732 sys_mbox_free(&conn->acceptmbox);
00733 sys_mbox_set_invalid(&conn->acceptmbox);
00734 }
00735 #endif
00736 }
00737
00738 #if LWIP_TCP
00739
00740
00741
00742
00743
00744
00745
00746 static void
00747 do_close_internal(struct netconn *conn)
00748 {
00749 err_t err;
00750 u8_t shut, shut_rx, shut_tx, close;
00751
00752 LWIP_ASSERT("invalid conn", (conn != NULL));
00753 LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
00754 LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
00755 LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
00756 LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
00757
00758 shut = conn->current_msg->msg.sd.shut;
00759 shut_rx = shut & NETCONN_SHUT_RD;
00760 shut_tx = shut & NETCONN_SHUT_WR;
00761
00762 close = shut == NETCONN_SHUT_RDWR;
00763
00764
00765 if (close) {
00766 tcp_arg(conn->pcb.tcp, NULL);
00767 }
00768 if (conn->pcb.tcp->state == LISTEN) {
00769 tcp_accept(conn->pcb.tcp, NULL);
00770 } else {
00771
00772 if (shut_rx) {
00773 tcp_recv(conn->pcb.tcp, NULL);
00774 tcp_accept(conn->pcb.tcp, NULL);
00775 }
00776 if (shut_tx) {
00777 tcp_sent(conn->pcb.tcp, NULL);
00778 }
00779 if (close) {
00780 tcp_poll(conn->pcb.tcp, NULL, 4);
00781 tcp_err(conn->pcb.tcp, NULL);
00782 }
00783 }
00784
00785 if (close) {
00786 err = tcp_close(conn->pcb.tcp);
00787 } else {
00788 err = tcp_shutdown(conn->pcb.tcp, shut_rx, shut_tx);
00789 }
00790 if (err == ERR_OK) {
00791
00792 conn->current_msg->err = ERR_OK;
00793 conn->current_msg = NULL;
00794 conn->state = NETCONN_NONE;
00795 if (close) {
00796
00797 conn->pcb.tcp = NULL;
00798
00799
00800 API_EVENT(conn, NETCONN_EVT_ERROR, 0);
00801 }
00802 if (shut_rx) {
00803 API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
00804 }
00805 if (shut_tx) {
00806 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
00807 }
00808
00809 sys_sem_signal(&conn->op_completed);
00810 } else {
00811
00812
00813 LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
00814 tcp_sent(conn->pcb.tcp, sent_tcp);
00815 tcp_poll(conn->pcb.tcp, poll_tcp, 4);
00816 tcp_err(conn->pcb.tcp, err_tcp);
00817 tcp_arg(conn->pcb.tcp, conn);
00818
00819 }
00820
00821
00822 }
00823 #endif
00824
00825
00826
00827
00828
00829
00830
00831 void
00832 do_delconn(struct api_msg_msg *msg)
00833 {
00834
00835 if ((msg->conn->state != NETCONN_NONE) &&
00836 (msg->conn->state != NETCONN_LISTEN) &&
00837 (msg->conn->state != NETCONN_CONNECT)) {
00838
00839 LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
00840 msg->err = ERR_INPROGRESS;
00841 } else {
00842 LWIP_ASSERT("blocking connect in progress",
00843 (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
00844
00845 netconn_drain(msg->conn);
00846
00847 if (msg->conn->pcb.tcp != NULL) {
00848
00849 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
00850 #if LWIP_RAW
00851 case NETCONN_RAW:
00852 raw_remove(msg->conn->pcb.raw);
00853 break;
00854 #endif
00855 #if LWIP_UDP
00856 case NETCONN_UDP:
00857 msg->conn->pcb.udp->recv_arg = NULL;
00858 udp_remove(msg->conn->pcb.udp);
00859 break;
00860 #endif
00861 #if LWIP_TCP
00862 case NETCONN_TCP:
00863 LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
00864 msg->conn->write_offset == 0);
00865 msg->conn->state = NETCONN_CLOSE;
00866 msg->msg.sd.shut = NETCONN_SHUT_RDWR;
00867 msg->conn->current_msg = msg;
00868 do_close_internal(msg->conn);
00869
00870
00871 return;
00872 #endif
00873 default:
00874 break;
00875 }
00876 msg->conn->pcb.tcp = NULL;
00877 }
00878
00879
00880
00881
00882 API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
00883 API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
00884 }
00885 if (sys_sem_valid(&msg->conn->op_completed)) {
00886 sys_sem_signal(&msg->conn->op_completed);
00887 }
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897 void
00898 do_bind(struct api_msg_msg *msg)
00899 {
00900 if (ERR_IS_FATAL(msg->conn->last_err)) {
00901 msg->err = msg->conn->last_err;
00902 } else {
00903 msg->err = ERR_VAL;
00904 if (msg->conn->pcb.tcp != NULL) {
00905 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
00906 #if LWIP_RAW
00907 case NETCONN_RAW:
00908 msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
00909 break;
00910 #endif
00911 #if LWIP_UDP
00912 case NETCONN_UDP:
00913 msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
00914 break;
00915 #endif
00916 #if LWIP_TCP
00917 case NETCONN_TCP:
00918 msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
00919 break;
00920 #endif
00921 default:
00922 break;
00923 }
00924 }
00925 }
00926 TCPIP_APIMSG_ACK(msg);
00927 }
00928
00929 #if LWIP_TCP
00930
00931
00932
00933
00934
00935
00936 static err_t
00937 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
00938 {
00939 struct netconn *conn;
00940 int was_blocking;
00941
00942 LWIP_UNUSED_ARG(pcb);
00943
00944 conn = (struct netconn *)arg;
00945
00946 if (conn == NULL) {
00947 return ERR_VAL;
00948 }
00949
00950 LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
00951 LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
00952 (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
00953
00954 if (conn->current_msg != NULL) {
00955 conn->current_msg->err = err;
00956 }
00957 if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
00958 setup_tcp(conn);
00959 }
00960 was_blocking = !IN_NONBLOCKING_CONNECT(conn);
00961 SET_NONBLOCKING_CONNECT(conn, 0);
00962 conn->current_msg = NULL;
00963 conn->state = NETCONN_NONE;
00964 if (!was_blocking) {
00965 NETCONN_SET_SAFE_ERR(conn, ERR_OK);
00966 }
00967 API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
00968
00969 if (was_blocking) {
00970 sys_sem_signal(&conn->op_completed);
00971 }
00972 return ERR_OK;
00973 }
00974 #endif
00975
00976
00977
00978
00979
00980
00981
00982
00983 void
00984 do_connect(struct api_msg_msg *msg)
00985 {
00986 if (msg->conn->pcb.tcp == NULL) {
00987
00988 msg->err = ERR_CLSD;
00989 } else {
00990 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
00991 #if LWIP_RAW
00992 case NETCONN_RAW:
00993 msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
00994 break;
00995 #endif
00996 #if LWIP_UDP
00997 case NETCONN_UDP:
00998 msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
00999 break;
01000 #endif
01001 #if LWIP_TCP
01002 case NETCONN_TCP:
01003
01004 if (msg->conn->state != NETCONN_NONE) {
01005 msg->err = ERR_ISCONN;
01006 } else {
01007 setup_tcp(msg->conn);
01008 msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr,
01009 msg->msg.bc.port, do_connected);
01010 if (msg->err == ERR_OK) {
01011 u8_t non_blocking = netconn_is_nonblocking(msg->conn);
01012 msg->conn->state = NETCONN_CONNECT;
01013 SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
01014 if (non_blocking) {
01015 msg->err = ERR_INPROGRESS;
01016 } else {
01017 msg->conn->current_msg = msg;
01018
01019
01020 return;
01021 }
01022 }
01023 }
01024 break;
01025 #endif
01026 default:
01027 LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0));
01028 break;
01029 }
01030 }
01031 sys_sem_signal(&msg->conn->op_completed);
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041 void
01042 do_disconnect(struct api_msg_msg *msg)
01043 {
01044 #if LWIP_UDP
01045 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
01046 udp_disconnect(msg->conn->pcb.udp);
01047 msg->err = ERR_OK;
01048 } else
01049 #endif
01050 {
01051 msg->err = ERR_VAL;
01052 }
01053 TCPIP_APIMSG_ACK(msg);
01054 }
01055
01056 #if LWIP_TCP
01057
01058
01059
01060
01061
01062
01063 void
01064 do_listen(struct api_msg_msg *msg)
01065 {
01066 if (ERR_IS_FATAL(msg->conn->last_err)) {
01067 msg->err = msg->conn->last_err;
01068 } else {
01069 msg->err = ERR_CONN;
01070 if (msg->conn->pcb.tcp != NULL) {
01071 if (msg->conn->type == NETCONN_TCP) {
01072 if (msg->conn->state == NETCONN_NONE) {
01073 #if TCP_LISTEN_BACKLOG
01074 struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
01075 #else
01076 struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
01077 #endif
01078 if (lpcb == NULL) {
01079
01080 msg->err = ERR_MEM;
01081 } else {
01082
01083 if (sys_mbox_valid(&msg->conn->recvmbox)) {
01084
01085 sys_mbox_free(&msg->conn->recvmbox);
01086 sys_mbox_set_invalid(&msg->conn->recvmbox);
01087 }
01088 msg->err = ERR_OK;
01089 if (!sys_mbox_valid(&msg->conn->acceptmbox)) {
01090 msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
01091 }
01092 if (msg->err == ERR_OK) {
01093 msg->conn->state = NETCONN_LISTEN;
01094 msg->conn->pcb.tcp = lpcb;
01095 tcp_arg(msg->conn->pcb.tcp, msg->conn);
01096 tcp_accept(msg->conn->pcb.tcp, accept_function);
01097 } else {
01098
01099 tcp_close(lpcb);
01100 msg->conn->pcb.tcp = NULL;
01101 }
01102 }
01103 }
01104 } else {
01105 msg->err = ERR_ARG;
01106 }
01107 }
01108 }
01109 TCPIP_APIMSG_ACK(msg);
01110 }
01111 #endif
01112
01113
01114
01115
01116
01117
01118
01119 void
01120 do_send(struct api_msg_msg *msg)
01121 {
01122 if (ERR_IS_FATAL(msg->conn->last_err)) {
01123 msg->err = msg->conn->last_err;
01124 } else {
01125 msg->err = ERR_CONN;
01126 if (msg->conn->pcb.tcp != NULL) {
01127 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
01128 #if LWIP_RAW
01129 case NETCONN_RAW:
01130 if (ip_addr_isany(&msg->msg.b->addr)) {
01131 msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
01132 } else {
01133 msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
01134 }
01135 break;
01136 #endif
01137 #if LWIP_UDP
01138 case NETCONN_UDP:
01139 #if LWIP_CHECKSUM_ON_COPY
01140 if (ip_addr_isany(&msg->msg.b->addr)) {
01141 msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
01142 msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
01143 } else {
01144 msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
01145 &msg->msg.b->addr, msg->msg.b->port,
01146 msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
01147 }
01148 #else
01149 if (ip_addr_isany(&msg->msg.b->addr)) {
01150 msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
01151 } else {
01152 msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
01153 }
01154 #endif
01155 break;
01156 #endif
01157 default:
01158 break;
01159 }
01160 }
01161 }
01162 TCPIP_APIMSG_ACK(msg);
01163 }
01164
01165 #if LWIP_TCP
01166
01167
01168
01169
01170
01171
01172 void
01173 do_recv(struct api_msg_msg *msg)
01174 {
01175 msg->err = ERR_OK;
01176 if (msg->conn->pcb.tcp != NULL) {
01177 if (msg->conn->type == NETCONN_TCP) {
01178 #if TCP_LISTEN_BACKLOG
01179 if (msg->conn->pcb.tcp->state == LISTEN) {
01180 tcp_accepted(msg->conn->pcb.tcp);
01181 } else
01182 #endif
01183 {
01184 u32_t remaining = msg->msg.r.len;
01185 do {
01186 u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
01187 tcp_recved(msg->conn->pcb.tcp, recved);
01188 remaining -= recved;
01189 }while(remaining != 0);
01190 }
01191 }
01192 }
01193 TCPIP_APIMSG_ACK(msg);
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 static err_t
01208 do_writemore(struct netconn *conn)
01209 {
01210 err_t err;
01211 void *dataptr;
01212 u16_t len, available;
01213 u8_t write_finished = 0;
01214 size_t diff;
01215 u8_t dontblock = netconn_is_nonblocking(conn) ||
01216 (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK);
01217 u8_t apiflags = conn->current_msg->msg.w.apiflags;
01218
01219 LWIP_ASSERT("conn != NULL", conn != NULL);
01220 LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
01221 LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
01222 LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
01223 LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
01224 conn->write_offset < conn->current_msg->msg.w.len);
01225
01226 #if LWIP_SO_SNDTIMEO
01227 if ((conn->send_timeout != 0) &&
01228 ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) {
01229 write_finished = 1;
01230 if (conn->write_offset == 0) {
01231
01232 err = ERR_WOULDBLOCK;
01233 conn->current_msg->msg.w.len = 0;
01234 } else {
01235
01236 err = ERR_OK;
01237 conn->current_msg->msg.w.len = conn->write_offset;
01238 }
01239 } else
01240 #endif
01241 {
01242 dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
01243 diff = conn->current_msg->msg.w.len - conn->write_offset;
01244 if (diff > 0xffffUL) {
01245 len = 0xffff;
01246 #if LWIP_TCPIP_CORE_LOCKING
01247 conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
01248 #endif
01249 apiflags |= TCP_WRITE_FLAG_MORE;
01250 } else {
01251 len = (u16_t)diff;
01252 }
01253 available = tcp_sndbuf(conn->pcb.tcp);
01254 if (available < len) {
01255
01256 len = available;
01257 if (dontblock){
01258 if (!len) {
01259 err = ERR_WOULDBLOCK;
01260 goto err_mem;
01261 }
01262 } else {
01263 #if LWIP_TCPIP_CORE_LOCKING
01264 conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
01265 #endif
01266 apiflags |= TCP_WRITE_FLAG_MORE;
01267 }
01268 }
01269 LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len));
01270 err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
01271
01272 if ((err == ERR_OK) || (err == ERR_MEM)) {
01273 err_mem:
01274 if (dontblock && (len < conn->current_msg->msg.w.len)) {
01275
01276
01277 API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
01278 conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
01279 } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) ||
01280 (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) {
01281
01282
01283 API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
01284 }
01285 }
01286
01287 if (err == ERR_OK) {
01288 conn->write_offset += len;
01289 if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) {
01290
01291 conn->current_msg->msg.w.len = conn->write_offset;
01292
01293 write_finished = 1;
01294 conn->write_offset = 0;
01295 }
01296 tcp_output(conn->pcb.tcp);
01297 } else if ((err == ERR_MEM) && !dontblock) {
01298
01299
01300
01301
01302
01303 tcp_output(conn->pcb.tcp);
01304
01305 #if LWIP_TCPIP_CORE_LOCKING
01306 conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
01307 #endif
01308 } else {
01309
01310
01311 write_finished = 1;
01312 conn->current_msg->msg.w.len = 0;
01313 }
01314 }
01315 if (write_finished) {
01316
01317
01318 conn->current_msg->err = err;
01319 conn->current_msg = NULL;
01320 conn->state = NETCONN_NONE;
01321 #if LWIP_TCPIP_CORE_LOCKING
01322 if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0)
01323 #endif
01324 {
01325 sys_sem_signal(&conn->op_completed);
01326 }
01327 }
01328 #if LWIP_TCPIP_CORE_LOCKING
01329 else
01330 return ERR_MEM;
01331 #endif
01332 return ERR_OK;
01333 }
01334 #endif
01335
01336
01337
01338
01339
01340
01341
01342 void
01343 do_write(struct api_msg_msg *msg)
01344 {
01345 if (ERR_IS_FATAL(msg->conn->last_err)) {
01346 msg->err = msg->conn->last_err;
01347 } else {
01348 if (msg->conn->type == NETCONN_TCP) {
01349 #if LWIP_TCP
01350 if (msg->conn->state != NETCONN_NONE) {
01351
01352 msg->err = ERR_INPROGRESS;
01353 } else if (msg->conn->pcb.tcp != NULL) {
01354 msg->conn->state = NETCONN_WRITE;
01355
01356 LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
01357 msg->conn->write_offset == 0);
01358 LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0);
01359 msg->conn->current_msg = msg;
01360 msg->conn->write_offset = 0;
01361 #if LWIP_TCPIP_CORE_LOCKING
01362 msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED;
01363 if (do_writemore(msg->conn) != ERR_OK) {
01364 LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
01365 UNLOCK_TCPIP_CORE();
01366 sys_arch_sem_wait(&msg->conn->op_completed, 0);
01367 LOCK_TCPIP_CORE();
01368 LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
01369 }
01370 #else
01371 do_writemore(msg->conn);
01372 #endif
01373
01374
01375 return;
01376 } else {
01377 msg->err = ERR_CONN;
01378 }
01379 #else
01380 msg->err = ERR_VAL;
01381 #endif
01382 #if (LWIP_UDP || LWIP_RAW)
01383 } else {
01384 msg->err = ERR_VAL;
01385 #endif
01386 }
01387 }
01388 TCPIP_APIMSG_ACK(msg);
01389 }
01390
01391
01392
01393
01394
01395
01396
01397 void
01398 do_getaddr(struct api_msg_msg *msg)
01399 {
01400 if (msg->conn->pcb.ip != NULL) {
01401 *(msg->msg.ad.ipaddr) = (msg->msg.ad.local ? msg->conn->pcb.ip->local_ip :
01402 msg->conn->pcb.ip->remote_ip);
01403
01404 msg->err = ERR_OK;
01405 switch (NETCONNTYPE_GROUP(msg->conn->type)) {
01406 #if LWIP_RAW
01407 case NETCONN_RAW:
01408 if (msg->msg.ad.local) {
01409 *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
01410 } else {
01411
01412 msg->err = ERR_CONN;
01413 }
01414 break;
01415 #endif
01416 #if LWIP_UDP
01417 case NETCONN_UDP:
01418 if (msg->msg.ad.local) {
01419 *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
01420 } else {
01421 if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
01422 msg->err = ERR_CONN;
01423 } else {
01424 *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
01425 }
01426 }
01427 break;
01428 #endif
01429 #if LWIP_TCP
01430 case NETCONN_TCP:
01431 *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
01432 break;
01433 #endif
01434 default:
01435 LWIP_ASSERT("invalid netconn_type", 0);
01436 break;
01437 }
01438 } else {
01439 msg->err = ERR_CONN;
01440 }
01441 TCPIP_APIMSG_ACK(msg);
01442 }
01443
01444
01445
01446
01447
01448
01449
01450 void
01451 do_close(struct api_msg_msg *msg)
01452 {
01453 #if LWIP_TCP
01454
01455 if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
01456
01457 LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
01458 msg->err = ERR_INPROGRESS;
01459 } else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
01460 if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
01461
01462 msg->err = ERR_CONN;
01463 } else {
01464 if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
01465
01466 netconn_drain(msg->conn);
01467 }
01468 LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
01469 msg->conn->write_offset == 0);
01470 msg->conn->state = NETCONN_CLOSE;
01471 msg->conn->current_msg = msg;
01472 do_close_internal(msg->conn);
01473
01474 return;
01475 }
01476 } else
01477 #endif
01478 {
01479 msg->err = ERR_VAL;
01480 }
01481 sys_sem_signal(&msg->conn->op_completed);
01482 }
01483
01484 #if LWIP_IGMP
01485
01486
01487
01488
01489
01490
01491 void
01492 do_join_leave_group(struct api_msg_msg *msg)
01493 {
01494 if (ERR_IS_FATAL(msg->conn->last_err)) {
01495 msg->err = msg->conn->last_err;
01496 } else {
01497 if (msg->conn->pcb.tcp != NULL) {
01498 if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
01499 #if LWIP_UDP
01500 if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
01501 msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
01502 } else {
01503 msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
01504 }
01505 #endif
01506 #if (LWIP_TCP || LWIP_RAW)
01507 } else {
01508 msg->err = ERR_VAL;
01509 #endif
01510 }
01511 } else {
01512 msg->err = ERR_CONN;
01513 }
01514 }
01515 TCPIP_APIMSG_ACK(msg);
01516 }
01517 #endif
01518
01519 #if LWIP_DNS
01520
01521
01522
01523
01524
01525 static void
01526 do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
01527 {
01528 struct dns_api_msg *msg = (struct dns_api_msg*)arg;
01529
01530 LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0);
01531 LWIP_UNUSED_ARG(name);
01532
01533 if (ipaddr == NULL) {
01534
01535 *msg->err = ERR_VAL;
01536 } else {
01537
01538 *msg->err = ERR_OK;
01539 *msg->addr = *ipaddr;
01540 }
01541
01542 sys_sem_signal(msg->sem);
01543 }
01544
01545
01546
01547
01548
01549
01550
01551 void
01552 do_gethostbyname(void *arg)
01553 {
01554 struct dns_api_msg *msg = (struct dns_api_msg*)arg;
01555
01556 *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg);
01557 if (*msg->err != ERR_INPROGRESS) {
01558
01559
01560 sys_sem_signal(msg->sem);
01561 }
01562 }
01563 #endif
01564
01565 #endif