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
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 #include <cfg/os.h>
00179 #include <sys/types.h>
00180 #include <string.h>
00181
00182 #include <sys/atom.h>
00183 #include <sys/heap.h>
00184 #include <sys/thread.h>
00185 #include <sys/event.h>
00186 #include <sys/timer.h>
00187
00188 #include <net/errno.h>
00189 #include <net/route.h>
00190 #include <netinet/in.h>
00191 #include <netinet/ip.h>
00192 #include <netinet/icmp.h>
00193 #include <netinet/ip_icmp.h>
00194 #include <netinet/ipcsum.h>
00195 #include <sys/socket.h>
00196 #include <netinet/tcp.h>
00197 #include <stdio.h>
00198 #include <io.h>
00199
00200 #ifdef NUTDEBUG
00201 #include <net/netdebug.h>
00202 #endif
00203
00204 #define TICK_RATE 1
00205
00210
00211 TCPSOCKET *tcpSocketList = 0;
00213 static volatile u_short last_local_port = 4096;
00214
00215 static u_char tcpStateRunning = 0;
00216
00217 void NutTcpDiscardBuffers(TCPSOCKET * sock)
00218 {
00219 NETBUF *nb;
00220 while ((nb = sock->so_rx_buf) != 0) {
00221 sock->so_rx_buf = nb->nb_next;
00222 NutNetBufFree(nb);
00223 }
00224 while ((nb = sock->so_tx_nbq) != 0) {
00225 sock->so_tx_nbq = nb->nb_next;
00226 NutNetBufFree(nb);
00227 }
00228 while ((nb = sock->so_rx_nbq) != 0) {
00229 sock->so_rx_nbq = nb->nb_next;
00230 NutNetBufFree(nb);
00231 }
00232 }
00233
00234
00246 void NutTcpDestroySocket(TCPSOCKET * sock)
00247 {
00248 TCPSOCKET *sp;
00249 TCPSOCKET *volatile *spp;
00250
00251
00252
00253
00254
00255
00256 sp = tcpSocketList;
00257 spp = &tcpSocketList;
00258 while (sp) {
00259 if (sp == sock) {
00260 *spp = sp->so_next;
00261 break;
00262 }
00263 spp = &sp->so_next;
00264 sp = sp->so_next;
00265 }
00266
00267
00268
00269
00270 if (sp) {
00271 NutTcpDiscardBuffers(sock);
00272 if (sock->so_devocnt)
00273 {
00274 NutHeapFree(sock->so_devobuf);
00275 sock->so_devocnt = 0;
00276 }
00277 memset(sock, 0, sizeof(TCPSOCKET));
00278 NutHeapFree(sock);
00279 }
00280 }
00281
00296 TCPSOCKET *NutTcpFindSocket(u_short lport, u_short rport, u_long raddr)
00297 {
00298 TCPSOCKET *sp;
00299 TCPSOCKET *sock = 0;
00300
00301
00302
00303
00304
00305 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00306 if (sp->so_local_port == lport) {
00307 if (sp->so_remote_addr == raddr && sp->so_remote_port == rport && sp->so_state != TCPS_CLOSED) {
00308 sock = sp;
00309 break;
00310 }
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 if (sock == 0) {
00322 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00323 if (sp->so_state == TCPS_LISTEN && sp->so_local_port == lport) {
00324 sock = sp;
00325 break;
00326 }
00327 }
00328 }
00329
00330 return sock;
00331 }
00332
00333
00348 TCPSOCKET *NutTcpCreateSocket(void)
00349 {
00350 TCPSOCKET *sock = 0;
00351
00352 if (tcpStateRunning || (tcpStateRunning = (NutTcpInitStateMachine() == 0))) {
00353
00354 if ((sock = NutHeapAllocClear(sizeof(TCPSOCKET))) != 0) {
00355 sock->so_state = TCPS_CLOSED;
00356
00357
00358
00359
00360 sock->so_devtype = IFTYP_TCPSOCK;
00361 sock->so_devread = NutTcpDeviceRead;
00362 sock->so_devwrite = NutTcpDeviceWrite;
00363 #ifdef __HARVARD_ARCH__
00364 sock->so_devwrite_P = NutTcpDeviceWrite_P;
00365 #endif
00366 sock->so_devioctl = NutTcpDeviceIOCtl;
00367
00368 sock->so_tx_isn = NutGetTickCount();
00369 sock->so_tx_una = sock->so_tx_isn;
00370 sock->so_tx_nxt = sock->so_tx_isn;
00371 sock->so_rx_bsz = sock->so_rx_win = TCP_WINSIZE;
00372
00373 sock->so_mss = TCP_MSS;
00374 sock->so_rtto = 1000;
00375
00376 sock->so_next = tcpSocketList;
00377
00378 sock->so_devobsz = TCP_MSS;
00379
00380 tcpSocketList = sock;
00381 }
00382 }
00383 return sock;
00384 }
00385
00405 int NutTcpSetSockOpt(TCPSOCKET * sock, int optname, CONST void *optval, int optlen)
00406 {
00407 int rc = -1;
00408
00409 if (sock == 0)
00410 return -1;
00411 switch (optname) {
00412
00413 case TCP_MAXSEG:
00414 if (optval == 0 || optlen != sizeof(u_short))
00415 sock->so_last_error = EINVAL;
00416 else if (sock->so_state != TCPS_CLOSED)
00417 sock->so_last_error = EISCONN;
00418 else {
00419 sock->so_mss = *((u_short *) optval);
00420 rc = 0;
00421 }
00422 break;
00423
00424 case SO_RCVBUF:
00425 if (optval == 0 || optlen != sizeof(u_short))
00426 sock->so_last_error = EINVAL;
00427 else {
00428 sock->so_rx_bsz = *((u_short *) optval);
00429 sock->so_rx_win = sock->so_rx_bsz;
00430 rc = 0;
00431 }
00432 break;
00433
00434 case SO_SNDTIMEO:
00435 if (optval == 0 || optlen != sizeof(u_long))
00436 sock->so_last_error = EINVAL;
00437 else {
00438 sock->so_write_to = *((u_long *) optval);
00439 rc = 0;
00440 }
00441 break;
00442
00443 case SO_RCVTIMEO:
00444 if (optval == 0 || optlen != sizeof(u_long))
00445 sock->so_last_error = EINVAL;
00446 else {
00447 sock->so_read_to = *((u_long *) optval);
00448 rc = 0;
00449 }
00450 break;
00451
00452 case SO_SNDBUF:
00453 if (optval == 0 || optlen != sizeof(u_short))
00454 sock->so_last_error = EINVAL;
00455 else {
00456 NutTcpDeviceWrite(sock, 0, 0);
00457 sock->so_devobsz = *((u_short *) optval);
00458 rc = 0;
00459 }
00460 break;
00461
00462 default:
00463 sock->so_last_error = ENOPROTOOPT;
00464 break;
00465 }
00466 return rc;
00467 }
00468
00488 int NutTcpGetSockOpt(TCPSOCKET * sock, int optname, void *optval, int optlen)
00489 {
00490 int rc = -1;
00491
00492 if (sock == 0)
00493 return -1;
00494 switch (optname) {
00495
00496 case TCP_MAXSEG:
00497 if (optval == 0 || optlen != sizeof(u_short))
00498 sock->so_last_error = EINVAL;
00499 else {
00500 *((u_short *) optval) = sock->so_mss;
00501 rc = 0;
00502 }
00503 break;
00504
00505 case SO_RCVBUF:
00506 if (optval == 0 || optlen != sizeof(u_short))
00507 sock->so_last_error = EINVAL;
00508 else {
00509 *((u_short *) optval) = sock->so_rx_bsz;
00510 rc = 0;
00511 }
00512 break;
00513
00514 case SO_SNDTIMEO:
00515 if (optval == 0 || optlen != sizeof(u_long))
00516 sock->so_last_error = EINVAL;
00517 else {
00518 *((u_long *) optval) = sock->so_write_to;
00519 rc = 0;
00520 }
00521 break;
00522
00523 case SO_RCVTIMEO:
00524 if (optval == 0 || optlen != sizeof(u_long))
00525 sock->so_last_error = EINVAL;
00526 else {
00527 *((u_long *) optval) = sock->so_read_to;
00528 rc = 0;
00529 }
00530 break;
00531
00532 case SO_SNDBUF:
00533 if (optval == 0 || optlen != sizeof(u_short))
00534 sock->so_last_error = EINVAL;
00535 else {
00536 *((u_short *) optval) = sock->so_devobsz;
00537 rc = 0;
00538 }
00539 break;
00540 default:
00541 sock->so_last_error = ENOPROTOOPT;
00542 break;
00543 }
00544 return rc;
00545 }
00546
00565 int NutTcpConnect(TCPSOCKET * sock, u_long addr, u_short port)
00566 {
00567 TCPSOCKET *sp;
00568 NUTDEVICE *dev;
00569
00570 if (sock == 0)
00571 return -1;
00572
00573
00574
00575
00576 if (sock->so_state == TCPS_LISTEN) {
00577 sock->so_last_error = EOPNOTSUPP;
00578 return -1;
00579 } else if (sock->so_state != TCPS_CLOSED) {
00580 sock->so_last_error = EISCONN;
00581 return -1;
00582 }
00583
00584
00585
00586
00587 do {
00588 if (++last_local_port == 0)
00589 last_local_port = 4096;
00590
00591 sp = tcpSocketList;
00592 while (sp) {
00593
00594 if (sp->so_local_port == htons(last_local_port))
00595 break;
00596 sp = sp->so_next;
00597 }
00598 } while (sp);
00599
00600
00601
00602
00603
00604 sock->so_local_port = htons(last_local_port);
00605 sock->so_remote_port = htons(port);
00606 sock->so_remote_addr = addr;
00607
00608
00609
00610
00611 if ((dev = NutIpRouteQuery(addr, 0)) != 0) {
00612 IFNET *nif = dev->dev_icb;
00613 sock->so_local_addr = nif->if_local_ip;
00614 } else {
00615 sock->so_last_error = EHOSTUNREACH;
00616 return -1;
00617 }
00618
00619
00620
00621
00622
00623 return NutTcpStateActiveOpenEvent(sock);
00624 }
00625
00641 int NutTcpAccept(TCPSOCKET * sock, u_short port)
00642 {
00643 sock->so_local_port = htons(port);
00644
00645 return NutTcpStatePassiveOpenEvent(sock);
00646 }
00647
00664 int NutTcpSend(TCPSOCKET * sock, CONST void *data, u_short len)
00665 {
00666 u_short unacked;
00667
00668
00669
00670
00671 NutThreadYield();
00672
00673 if (sock == 0)
00674 return -1;
00675 if (data == 0 || len == 0)
00676 return 0;
00677
00678
00679
00680
00681 if (len > sock->so_mss)
00682 len = sock->so_mss;
00683
00684 for (;;) {
00685
00686
00687
00688 if (sock->so_state != TCPS_ESTABLISHED) {
00689 sock->so_last_error = ENOTCONN;
00690 return -1;
00691 }
00692
00693
00694
00695
00696
00697
00698 unacked = sock->so_tx_nxt - sock->so_tx_una;
00699 if ((unacked >> 2) < sock->so_mss && len <= sock->so_tx_win - unacked) {
00700 break;
00701 }
00702 if (NutEventWait(&sock->so_tx_tq, sock->so_write_to)) {
00703 return 0;
00704 }
00705 }
00706
00707
00708
00709
00710
00711 sock->so_tx_flags |= SO_ACK;
00712 if (NutTcpOutput(sock, data, len))
00713 return -1;
00714 return len;
00715 }
00716
00734 int NutTcpReceive(TCPSOCKET * sock, void *data, u_short size)
00735 {
00736 u_short i;
00737
00738 NutThreadYield();
00739
00740
00741
00742 if (sock == 0)
00743 return -1;
00744 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT) {
00745 sock->so_last_error = ENOTCONN;
00746 return -1;
00747 }
00748 if (data == 0 || size == 0)
00749 return 0;
00750
00751
00752
00753
00754
00755 while (sock->so_rx_cnt - sock->so_rd_cnt == 0) {
00756 if (sock->so_state != TCPS_ESTABLISHED) {
00757 sock->so_last_error = ENOTCONN;
00758 return -1;
00759 }
00760 if (NutEventWait(&sock->so_rx_tq, sock->so_read_to))
00761 return 0;
00762 }
00763
00764 if (size > sock->so_rx_cnt - sock->so_rd_cnt)
00765 size = sock->so_rx_cnt - sock->so_rd_cnt;
00766 if (size) {
00767 NETBUF *nb;
00768 u_short rd_cnt;
00769 u_short nb_cnt;
00770 u_short ab_cnt;
00771 u_short mv_cnt;
00772
00773 rd_cnt = sock->so_rd_cnt;
00774
00775 ab_cnt = 0;
00776 while (ab_cnt < size) {
00777 nb = sock->so_rx_buf;
00778 nb_cnt = nb->nb_ap.sz - rd_cnt;
00779 mv_cnt = size - ab_cnt;
00780 if (mv_cnt > nb_cnt)
00781 mv_cnt = nb_cnt;
00782 memcpy((char *) data + ab_cnt, (char *) (nb->nb_ap.vp) + rd_cnt, mv_cnt);
00783 ab_cnt += mv_cnt;
00784 rd_cnt += mv_cnt;
00785 if (mv_cnt >= nb_cnt) {
00786 sock->so_rx_buf = nb->nb_next;
00787 sock->so_rx_cnt -= rd_cnt;
00788 NutNetBufFree(nb);
00789 nb = sock->so_rx_buf;
00790 rd_cnt = 0;
00791 }
00792 }
00793 sock->so_rd_cnt = rd_cnt;
00794
00795
00796
00797
00798 if (sock->so_state == TCPS_ESTABLISHED) {
00799 i = sock->so_rx_win;
00800 if ((i += size) > sock->so_rx_bsz)
00801 i = sock->so_rx_bsz;
00802
00803 if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
00804 sock->so_rx_win = i;
00805 NutTcpStateWindowEvent(sock);
00806 } else {
00807 sock->so_rx_win = i;
00808 }
00809 }
00810 }
00811 return size;
00812 }
00813
00826 int NutTcpCloseSocket(TCPSOCKET * sock)
00827 {
00828
00829
00830 NutTcpDeviceWrite(sock, 0, 0);
00831 return NutTcpStateCloseEvent(sock);
00832 }
00833
00882 int NutTcpError(TCPSOCKET * sock)
00883 {
00884 if (sock == 0)
00885 return ENOTSOCK;
00886 return sock->so_last_error;
00887 }
00888
00908 int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
00909 {
00910 return NutTcpReceive(sock, buffer, size);
00911 }
00912
00913 static int SendBuffer(TCPSOCKET * sock, CONST void *buffer, int size)
00914 {
00915 int rc;
00916 int bite;
00917
00918 for (rc = 0; rc < size; rc += bite) {
00919 if ((bite = NutTcpSend(sock, (u_char *) buffer + rc, size - rc)) <= 0) {
00920 return -1;
00921 }
00922 }
00923 return rc;
00924 }
00925
00948 int NutTcpDeviceWrite(TCPSOCKET * sock, CONST void *buf, int size)
00949 {
00950 int rc;
00951 u_short sz;
00952
00953 u_char *buffer = (u_char*) buf;
00954
00955
00956
00957
00958 if (sock == 0)
00959 return -1;
00960 if (sock->so_state != TCPS_ESTABLISHED) {
00961 sock->so_last_error = ENOTCONN;
00962 return -1;
00963 }
00964
00965
00966 if (size == 0) {
00967 if (sock->so_devocnt) {
00968 if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
00969 NutHeapFree(sock->so_devobuf);
00970 sock->so_devocnt = 0;
00971 return -1;
00972 }
00973 NutHeapFree(sock->so_devobuf);
00974 sock->so_devocnt = 0;
00975 }
00976 return 0;
00977 }
00978
00979
00980 if (sock->so_devocnt == 0) {
00981
00982
00983
00984
00985 if ((u_short) size >= sock->so_devobsz) {
00986 rc = size % sock->so_devobsz;
00987 if (SendBuffer(sock, buffer, size - rc) < 0)
00988 return -1;
00989 buffer += size - rc;
00990 } else
00991 rc = size;
00992
00993
00994
00995
00996 if (rc) {
00997 if (!(sock->so_devobuf = NutHeapAlloc(sock->so_devobsz)))
00998 return -1;
00999 memcpy(sock->so_devobuf, buffer, rc);
01000 sock->so_devocnt = rc;
01001 }
01002 return size;
01003 }
01004
01005
01006 if (sock->so_devocnt + size < sock->so_devobsz) {
01007 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
01008 sock->so_devocnt += size;
01009 return size;
01010 }
01011
01012
01013
01014
01015 sz = sock->so_devobsz - sock->so_devocnt;
01016 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
01017 buffer += sz;
01018 if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
01019 NutHeapFree(sock->so_devobuf);
01020 sock->so_devocnt = 0;
01021 return -1;
01022 }
01023
01024
01025
01026
01027
01028 sz = size - sz;
01029 if (sz >= sock->so_devobsz) {
01030 rc = size % sock->so_devobsz;
01031 if (SendBuffer(sock, buffer, sz - rc) < 0) {
01032 NutHeapFree(sock->so_devobuf);
01033 sock->so_devocnt = 0;
01034 return -1;
01035 }
01036 buffer += sz - rc;
01037 } else
01038 rc = sz;
01039
01040
01041
01042 if (rc)
01043 memcpy(sock->so_devobuf, buffer, rc);
01044 else
01045 NutHeapFree(sock->so_devobuf);
01046 sock->so_devocnt = rc;
01047
01048 return size;
01049 }
01050
01075 #ifdef __HARVARD_ARCH__
01076 int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
01077 {
01078 int rc;
01079 char *rp = 0;
01080
01081
01082
01083
01084
01085 if (size && (rp = NutHeapAlloc(size)) != 0)
01086 memcpy_P(rp, buffer, size);
01087 rc = NutTcpDeviceWrite(sock, rp, size);
01088 if (rp)
01089 NutHeapFree(rp);
01090
01091 return rc;
01092 }
01093 #endif
01094
01114 int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
01115 {
01116 u_long *lvp = (u_long *) param;
01117 int rc = 0;
01118
01119 switch (cmd) {
01120 case IOCTL_GETFILESIZE:
01121 case IOCTL_GETINBUFCOUNT:
01122 *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
01123 break;
01124 case IOCTL_GETOUTBUFCOUNT:
01125 *lvp = (sock->so_devocnt);
01126 break;
01127 default:
01128 rc = -1;
01129 }
01130
01131 return rc;
01132 }
01133