?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Berekely Socket Distribution API Source File
4 *
5 *********************************************************************
6 * FileName: BerkeleyAPI.c
7 * Description: Berkeley Socket Distribution(BSD) APIs for Microchip TCPIP Stack
8 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
9 * Compiler: Microchip C32 v1.05 or higher
10 * Microchip C30 v3.12 or higher
11 * Microchip C18 v3.30 or higher
12 * HI-TECH PICC-18 PRO 9.63PL2 or higher
13 * Company: Microchip Technology, Inc.
14 *
15 * Software License Agreement
16 *
17 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
18 * reserved.
19 *
20 * Microchip licenses to you the right to use, modify, copy, and
21 * distribute:
22 * (i) the Software when embedded on a Microchip microcontroller or
23 * digital signal controller product ("Device") which is
24 * integrated into Licensee's product; or
25 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
26 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
27 * used in conjunction with a Microchip ethernet controller for
28 * the sole purpose of interfacing with the ethernet controller.
29 *
30 * You should refer to the license agreement accompanying this
31 * Software for additional information regarding your rights and
32 * obligations.
33 *
34 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
35 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
36 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
37 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
38 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
39 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
40 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
41 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
42 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
43 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
44 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
45 *
46 * Author Date Comment
47 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 * Aseem Swalah 4/3/08 Original
49 ********************************************************************/
50  
51 #include "TCPIPConfig.h"
52  
53 #if defined(STACK_USE_BERKELEY_API)
54  
55 #include "TCPIP Stack/TCPIP.h"
56  
57 static BOOL HandlePossibleTCPDisconnection(SOCKET s);
58  
59  
60 #if defined(__18CXX) && !defined(HI_TECH_C)
61 #pragma udata BSD_uRAM
62 #endif
63 static struct BSDSocket BSDSocketArray[BSD_SOCKET_COUNT];
64 #if defined(__18CXX) && !defined(HI_TECH_C)
65 #pragma udata
66 #endif
67  
68 static WORD gAutoPortNumber = 1024;
69  
70  
71 /*****************************************************************************
72 Function:
73 void BerkeleySocketInit(void)
74  
75 Summary:
76 Initializes the Berkeley socket structure array.
77  
78 Description:
79 This function initializes the Berkeley socket array. This function should
80 be called before any BSD socket call.
81  
82 Precondition:
83 None.
84  
85 Parameters:
86 None.
87  
88 Returns:
89 None
90  
91 Remarks:
92 None.
93 ***************************************************************************/
94 void BerkeleySocketInit(void)
95 {
96 unsigned int s;
97 struct BSDSocket *socket;
98  
99 for ( s = 0; s < BSD_SOCKET_COUNT; s++ )
100 {
101 socket = (struct BSDSocket *)&BSDSocketArray[s];
102 socket->bsdState = SKT_CLOSED;
103 }
104 }
105  
106 /*****************************************************************************
107 Function:
108 SOCKET socket( int af, int type, int protocol )
109  
110 Summary:
111 This function creates a new Berkeley socket.
112  
113 Description:
114 This function creates a new BSD socket for the microchip
115 TCPIP stack. The return socket descriptor is used for the subsequent
116 BSD operations.
117  
118 Precondition:
119 BerkeleySocketInit function should be called.
120  
121 Parameters:
122 af - address family - AF_INET.
123 type - socket type SOCK_DGRAM or SOCK_STREAM.
124 protocol - IP protocol IPPROTO_UDP or IPPROTO_TCP.
125  
126 Returns:
127 New socket descriptor. INVALID_SOCKET in case of error.
128  
129 Remarks:
130 None.
131 ***************************************************************************/
132 SOCKET socket( int af, int type, int protocol )
133 {
134 struct BSDSocket *socket = BSDSocketArray;
135 SOCKET s;
136  
137 if( af != AF_INET )
138 return INVALID_SOCKET;
139  
140 for( s = 0; s < BSD_SOCKET_COUNT; s++,socket++ )
141 {
142 if( socket->bsdState != SKT_CLOSED ) //socket in use
143 continue;
144  
145 socket->SocketType = type;
146  
147 if( type == SOCK_DGRAM && protocol == IPPROTO_UDP )
148 {
149 socket->bsdState = SKT_CREATED;
150 return s;
151 }
152 else if( type == SOCK_STREAM && protocol == IPPROTO_TCP )
153 {
154 socket->bsdState = SKT_CREATED;
155 return s;
156 }
157 else
158 return INVALID_SOCKET;
159 }
160  
161 return INVALID_SOCKET;
162 }
163  
164 /*****************************************************************************
165 Function:
166 int bind( SOCKET s, const struct sockaddr* name, int namelen )
167  
168 Summary:
169 This function assigns a name to the socket descriptor.
170  
171 Description:
172 The bind function assigns a name to an unnamed socket. The
173 name represents the local address of the communication
174 endpoint. For sockets of type SOCK_STREAM, the name of the
175 remote endpoint is assigned when a connect or accept function
176 is executed.
177  
178 Precondition:
179 socket function should be called.
180  
181 Parameters:
182 s - Socket descriptor returned from a previous call to socket.
183 name - pointer to the sockaddr structure containing the
184 local address of the socket.
185 namelen - length of the sockaddr structure.
186  
187 Returns:
188 If bind is successful, a value of 0 is returned. A return
189 value of SOCKET_ERROR indicates an error.
190  
191 Remarks:
192 None.
193 ***************************************************************************/
194 int bind( SOCKET s, const struct sockaddr* name, int namelen )
195 {
196 struct BSDSocket *socket;
197 struct sockaddr_in *local_addr;
198 WORD lPort;
199  
200 if( s >= BSD_SOCKET_COUNT )
201 return SOCKET_ERROR;
202  
203 socket = &BSDSocketArray[s];
204  
205 if( socket->bsdState != SKT_CREATED ) //only work with recently created socket
206 return SOCKET_ERROR;
207  
208 if( (unsigned int)namelen < sizeof(struct sockaddr_in) )
209 return SOCKET_ERROR;
210  
211 local_addr = (struct sockaddr_in *)name;
212  
213 lPort = local_addr->sin_port;
214 if( lPort == 0u ) //pick a port
215 {
216 lPort = gAutoPortNumber++;
217 if(gAutoPortNumber > 5000u) // reset the port numbers
218 gAutoPortNumber = 1024;
219 }
220  
221 if(socket->SocketType == SOCK_DGRAM)
222 {
223 socket->SocketID = UDPOpen(lPort, NULL, 0);
224 if(socket->SocketID == INVALID_UDP_SOCKET)
225 return SOCKET_ERROR;
226 }
227  
228 socket->localPort = lPort;
229 socket->bsdState = SKT_BOUND;
230 return 0; //success
231 }
232  
233 /*****************************************************************************
234 Function:
235 int listen( SOCKET s, int backlog )
236  
237 Summary:
238 The listen function sets the specified socket in a listen mode
239  
240 Description:
241 This function sets the specified socket in a listen
242 mode. Calling the listen function indicates that the
243 application is ready to accept connection requests arriving
244 at a socket of type SOCK_STREAM. The connection request is
245 queued (if possible) until accepted with an accept function.
246 The backlog parameter defines the maximum number of pending
247 connections that may be queued.
248  
249 Precondition:
250 bind() must have been called on the s socket first.
251  
252 Parameters:
253 s - Socket identifier returned from a prior socket() call.
254 backlog - Maximum number of connection requests that can be queued. Note
255 that each backlog requires a TCP_PURPOSE_BERKELEY_SERVER type TCP
256 socket to be allocated in the TCPSocketInitializer[] in TCPIPConfig.h.
257 Also, ensure that BSD_SOCKET_COUNT (also in TCPIPConfig.h) is greater
258 than the backlog by at least 1 (more if you have other BSD sockets in
259 use).
260  
261 Returns:
262 Returns 0 on success, else return SOCKET_ERROR.
263  
264 Remarks:
265 None
266 ***************************************************************************/
267 int listen( SOCKET s, int backlog )
268 {
269 struct BSDSocket *ps;
270 SOCKET clientSockID;
271 unsigned int socketcount;
272 unsigned char assigned;
273  
274 if( s >= BSD_SOCKET_COUNT )
275 return SOCKET_ERROR;
276  
277 ps = &BSDSocketArray[s];
278  
279 if(ps->SocketType != SOCK_STREAM)
280 return SOCKET_ERROR;
281  
282 if(ps->bsdState == SKT_BSD_LISTEN)
283 backlog = ps->backlog;
284  
285 if((ps->bsdState != SKT_BOUND) && (ps->bsdState != SKT_BSD_LISTEN))
286 return SOCKET_ERROR;
287  
288 while(backlog--)
289 {
290 assigned = 0;
291 for(socketcount = 0; socketcount < BSD_SOCKET_COUNT; socketcount++)
292 {
293 if(BSDSocketArray[socketcount].bsdState != SKT_CLOSED)
294 continue;
295  
296 clientSockID = TCPOpen(0, TCP_OPEN_SERVER, ps->localPort, TCP_PURPOSE_BERKELEY_SERVER);
297 if(clientSockID == INVALID_SOCKET)
298 return SOCKET_ERROR;
299  
300 // Clear the first reset flag
301 TCPWasReset(clientSockID);
302  
303 assigned = 1;
304 ps->bsdState = SKT_BSD_LISTEN;
305 ps->backlog = backlog;
306  
307 BSDSocketArray[socketcount].SocketID = clientSockID;
308 BSDSocketArray[socketcount].bsdState = SKT_LISTEN;
309 BSDSocketArray[socketcount].isServer = TRUE;
310 BSDSocketArray[socketcount].localPort = ps->localPort;
311 BSDSocketArray[socketcount].SocketType = SOCK_STREAM;
312 break;
313 }
314 if(!assigned)
315 return SOCKET_ERROR;
316 }
317 return 0; //Success
318 }
319  
320  
321 /*****************************************************************************
322 Function:
323 SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)
324  
325 Summary:
326 This function accepts connection requests queued for a listening socket.
327  
328 Description:
329 The accept function is used to accept connection requests
330 queued for a listening socket. If a connection request is
331 pending, accept removes the request from the queue, and a new
332 socket is created for the connection. The original listening
333 socket remains open and continues to queue new connection
334 requests. The socket must be a SOCK_STREAM type socket.
335  
336 Precondition:
337 listen function should be called.
338  
339 Parameters:
340 s - Socket descriptor returned from a previous call to
341 socket. must be bound to a local name and in listening mode.
342 addr - Optional pointer to a buffer that receives the address
343 of the connecting entity.
344 addrlen - Optional pointer to an integer that contains the
345 length of the address addr
346  
347 Returns:
348 If the accept function succeeds, it returns a non-negative
349 integer that is a descriptor for the accepted socket.
350 Otherwise, the value INVALID_SOCKET is returned.
351  
352 Remarks:
353 None.
354 ***************************************************************************/
355 SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen)
356 {
357 struct BSDSocket *pListenSock;
358 SOCKET_INFO *remoteSockInfo;
359 struct sockaddr_in *addrRemote;
360 unsigned int sockCount;
361 TCP_SOCKET hTCP;
362  
363 if( s >= BSD_SOCKET_COUNT )
364 return INVALID_SOCKET;
365  
366 pListenSock = &BSDSocketArray[s]; /* Get the pointer to listening server socket */
367  
368 if ( pListenSock->bsdState != SKT_BSD_LISTEN )
369 return INVALID_SOCKET;
370 if ( pListenSock->SocketType != SOCK_STREAM )
371 return INVALID_SOCKET;
372  
373 for(sockCount = 0; sockCount < BSD_SOCKET_COUNT; sockCount++)
374 {
375 if(BSDSocketArray[sockCount].bsdState != SKT_LISTEN)
376 continue;
377  
378 if(BSDSocketArray[sockCount].localPort != pListenSock->localPort)
379 continue;
380  
381 hTCP = BSDSocketArray[sockCount].SocketID;
382  
383 // We don't care about connections and disconnections before we can
384 // process them, so clear the reset flag
385 TCPWasReset(hTCP);
386  
387 if(TCPIsConnected(hTCP))
388 {
389 remoteSockInfo = TCPGetRemoteInfo(hTCP);
390 if(addr)
391 {
392 if(addrlen)
393 {
394 if((unsigned int)*addrlen < sizeof(struct sockaddr_in))
395 return INVALID_SOCKET;
396 addrRemote = (struct sockaddr_in *)addr;
397 addrRemote->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
398 addrRemote->sin_port = remoteSockInfo->remotePort.Val;
399 *addrlen = sizeof(struct sockaddr_in);
400 }
401 }
402 BSDSocketArray[sockCount].remotePort = remoteSockInfo->remotePort.Val;
403 BSDSocketArray[sockCount].remoteIP = remoteSockInfo->remote.IPAddr.Val;
404 BSDSocketArray[sockCount].bsdState = SKT_EST;
405 return sockCount;
406 }
407 }
408  
409 return INVALID_SOCKET;
410 }
411  
412 /*****************************************************************************
413 Function:
414 int connect( SOCKET s, struct sockaddr* name, int namelen )
415  
416 Summary:
417 This function connects to the peer communications end point.
418  
419 Description:
420 The connect function assigns the address of the peer
421 communications endpoint. For stream sockets, connection is
422 established between the endpoints. For datagram sockets, an
423 address filter is established between the endpoints until
424 changed with another connect() function.
425  
426 Precondition:
427 socket function should be called.
428  
429 Parameters:
430 s - Socket descriptor returned from a previous call to socket.
431 name - pointer to the sockaddr structure containing the
432 peer address and port number.
433 namelen - length of the sockaddr structure.
434  
435 Returns:
436 If the connect() function succeeds, it returns 0. Otherwise,
437 the value SOCKET_ERROR is returned to indicate an error
438 condition. For stream based socket, if the connection is not
439 established yet, connect returns SOCKET_CNXN_IN_PROGRESS.
440  
441 Remarks:
442 None.
443 ***************************************************************************/
444 int connect( SOCKET s, struct sockaddr* name, int namelen )
445 {
446 struct BSDSocket *socket;
447 struct sockaddr_in *addr;
448 DWORD remoteIP;
449 WORD remotePort;
450 WORD localPort;
451  
452 if( s >= BSD_SOCKET_COUNT )
453 return SOCKET_ERROR;
454  
455 socket = &BSDSocketArray[s];
456  
457 if( socket->bsdState < SKT_CREATED )
458 return SOCKET_ERROR;
459  
460 if( (unsigned int)namelen < sizeof(struct sockaddr_in))
461 return SOCKET_ERROR;
462  
463 addr = (struct sockaddr_in *)name;
464 remotePort = addr->sin_port;
465 remoteIP = addr->sin_addr.S_un.S_addr;
466  
467 if( remoteIP == 0u || remotePort == 0u )
468 return SOCKET_ERROR;
469  
470 if( socket->SocketType == SOCK_STREAM )
471 {
472 switch(socket->bsdState)
473 {
474 case SKT_EST:
475 return 0; // already established
476  
477 case SKT_IN_PROGRESS:
478 if(HandlePossibleTCPDisconnection(s))
479 return SOCKET_ERROR;
480  
481 if(!TCPIsConnected(socket->SocketID))
482 return SOCKET_CNXN_IN_PROGRESS;
483  
484 socket->bsdState = SKT_EST;
485 return 0; //success
486  
487 case SKT_CREATED:
488 case SKT_BOUND:
489 socket->SocketID = TCPOpen(remoteIP, TCP_OPEN_IP_ADDRESS, remotePort, TCP_PURPOSE_BERKELEY_CLIENT);
490 if(socket->SocketID == INVALID_SOCKET)
491 return SOCKET_ERROR;
492  
493 // Clear the first reset flag
494 TCPWasReset(socket->SocketID);
495  
496 socket->isServer = FALSE;
497 socket->bsdState = SKT_IN_PROGRESS;
498 return SOCKET_CNXN_IN_PROGRESS;
499  
500 default:
501 return SOCKET_ERROR;
502 }
503 }
504 else
505 {
506 // If not explicitly bound to a local port, implicitly do the binding
507 if(socket->bsdState == SKT_CREATED)
508 {
509 localPort = gAutoPortNumber++;
510 if(gAutoPortNumber > 5000u) // reset the port numbers
511 gAutoPortNumber = 1024;
512  
513 socket->SocketID = UDPOpen(localPort, NULL, remotePort);
514 if(socket->SocketID == INVALID_UDP_SOCKET)
515 return SOCKET_ERROR;
516 socket->bsdState = SKT_BOUND;
517 }
518 if(socket->bsdState != SKT_BOUND)
519 return SOCKET_ERROR;
520  
521 // UDP: remote port is used as a filter. Need to call connect when using
522 // send/recv calls. No need to call 'connect' if using sendto/recvfrom
523 // calls.
524 socket->remotePort = remotePort;
525 socket->remoteIP = remoteIP;
526 return 0; //success
527 }
528 return SOCKET_ERROR;
529 }
530  
531 /*****************************************************************************
532 Function:
533 int send( SOCKET s, const char* buf, int len, int flags )
534  
535 Summary:
536 The send function is used to send outgoing data on an already
537 connected socket.
538  
539 Description:
540 The send function is used to send outgoing data on an already
541 connected socket. This function is used to send a reliable,
542 ordered stream of data bytes on a socket of type SOCK_STREAM
543 but can also be used to send datagrams on a socket of type SOCK_DGRAM.
544  
545 Precondition:
546 connect function should be called for TCP and UDP sockets.
547 Server side, accept function should be called.
548  
549 Parameters:
550 s - Socket descriptor returned from a previous call to socket.
551 buf - application data buffer containing data to transmit.
552 len - length of data in bytes.
553 flags - message flags. Currently this field is not supported.
554  
555 Returns:
556 On success, send returns number of bytes sent. In case of
557 error, returns SOCKET_ERROR. a zero indicates no data send.
558  
559 Remarks:
560 None.
561 ***************************************************************************/
562 int send( SOCKET s, const char* buf, int len, int flags )
563 {
564 return sendto(s, buf, len, flags, NULL, 0);
565 }
566  
567 /*****************************************************************************
568 Function:
569 int sendto(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)
570  
571 Summary:
572 This function used to send the data for both connection oriented and connection-less
573 sockets.
574  
575 Description:
576 The sendto function is used to send outgoing data on a socket.
577 The destination address is given by to and tolen. Both
578 Datagram and stream sockets are supported.
579  
580 Precondition:
581 socket function should be called.
582  
583 Parameters:
584 s - Socket descriptor returned from a previous call to socket.
585 buf - application data buffer containing data to transmit.
586 len - length of data in bytes.
587 flags - message flags. Currently this field is not supported.
588 to - Optional pointer to the the sockaddr structure containing the
589 destination address. If NULL, the currently bound remote port and IP
590 address are used as the destination.
591 tolen - length of the sockaddr structure.
592  
593 Returns:
594 On success, sendto returns number of bytes sent. In case of
595 error returns SOCKET_ERROR
596  
597 Remarks:
598 None.
599 ***************************************************************************/
600 int sendto( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
601 {
602 struct BSDSocket *socket;
603 int size = SOCKET_ERROR;
604 NODE_INFO remoteInfo;
605 static DWORD startTick; // NOTE: startTick really should be a per socket BSDSocket structure member since other BSD calls can interfere with the ARP cycles
606 WORD wRemotePort;
607 struct sockaddr_in local;
608  
609 if( s >= BSD_SOCKET_COUNT )
610 return SOCKET_ERROR;
611  
612 socket = &BSDSocketArray[s];
613  
614 if(socket->bsdState == SKT_CLOSED)
615 return SOCKET_ERROR;
616  
617 if(socket->SocketType == SOCK_DGRAM) //UDP
618 {
619 // Decide the destination IP address and port
620 remoteInfo.IPAddr.Val = socket->remoteIP;
621 wRemotePort = socket->remotePort;
622 if(to)
623 {
624 if((unsigned int)tolen != sizeof(struct sockaddr_in))
625 return SOCKET_ERROR;
626 wRemotePort = ((struct sockaddr_in*)to)->sin_port;
627 remoteInfo.IPAddr.Val = ((struct sockaddr_in*)to)->sin_addr.s_addr;
628  
629 // Implicitly bind the socket if it isn't already
630 if(socket->bsdState == SKT_CREATED)
631 {
632 memset(&local, 0x00, sizeof(local));
633 if(bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
634 return SOCKET_ERROR;
635 }
636 }
637 if(remoteInfo.IPAddr.Val == IP_ADDR_ANY)
638 remoteInfo.IPAddr.Val = 0xFFFFFFFFu;
639  
640 // Set the remote IP and MAC address if it is different from what we already have stored in the UDP socket
641 if(UDPSocketInfo[socket->SocketID].remoteNode.IPAddr.Val != remoteInfo.IPAddr.Val)
642 {
643 if(ARPIsResolved(&remoteInfo.IPAddr, &remoteInfo.MACAddr))
644 {
645 memcpy((void*)&UDPSocketInfo[socket->SocketID].remoteNode, (void*)&remoteInfo, sizeof(remoteInfo));
646 }
647 else
648 {
649 if(TickGet() - startTick > 1*TICK_SECOND)
650 {
651 ARPResolve(&remoteInfo.IPAddr);
652 startTick = TickGet();
653 }
654 return SOCKET_ERROR;
655 }
656 }
657  
658 // Select the UDP socket and see if we can write to it
659 if(UDPIsPutReady(socket->SocketID))
660 {
661 // Set the proper remote port
662 UDPSocketInfo[socket->SocketID].remotePort = wRemotePort;
663  
664 // Write data and send UDP datagram
665 size = UDPPutArray((BYTE*)buf, len);
666 UDPFlush();
667 return size;
668 }
669 }
670 else if(socket->SocketType == SOCK_STREAM) //TCP will only send to the already established socket.
671 {
672 if(socket->bsdState != SKT_EST)
673 return SOCKET_ERROR;
674  
675 if(HandlePossibleTCPDisconnection(s))
676 return SOCKET_ERROR;
677  
678 // Handle special case were 0 return value is okay
679 if(len == 0)
680 return 0;
681  
682 // Write data to the socket. If one or more bytes were written, then
683 // return this value. Otherwise, fail and return SOCKET_ERROR.
684 size = TCPPutArray(socket->SocketID, (BYTE*)buf, len);
685 if(size)
686 return size;
687 }
688 return SOCKET_ERROR;
689 }
690  
691 /*****************************************************************************
692 Function:
693 int recv( SOCKET s, char* buf, int len, int flags )
694  
695 Summary:
696 The recv() function is used to receive incoming data that has
697 been queued for a socket.
698  
699 Description:
700 The recv() function is used to receive incoming data that has
701 been queued for a socket. This function can be used with both
702 datagram and stream socket. If the available data
703 is too large to fit in the supplied application buffer buf,
704 excess bytes are discarded in case of SOCK_DGRAM type
705 sockets. For SOCK_STREAM types, the data is buffered
706 internally so the application can retreive all data by
707 multiple calls of recvfrom.
708  
709 Precondition:
710 connect function should be called for TCP and UDP sockets.
711 Server side, accept function should be called.
712  
713 Parameters:
714 s - Socket descriptor returned from a previous call to socket.
715 buf - application data receive buffer.
716 len - buffer length in bytes.
717 flags - no significance in this implementation
718  
719 Returns:
720 If recv is successful, the number of bytes copied to
721 application buffer buf is returned. A value of zero indicates
722 no data available. A return value of SOCKET_ERROR (-1)
723 indicates an error condition. A return value of SOCKET_DISCONNECTED
724 indicates the connection no longer exists.
725  
726 Remarks:
727 None.
728 ***************************************************************************/
729 int recv( SOCKET s, char* buf, int len, int flags )
730 {
731 struct BSDSocket *socket;
732  
733 if( s >= BSD_SOCKET_COUNT )
734 return SOCKET_ERROR;
735  
736 socket = &BSDSocketArray[s];
737  
738 if(socket->SocketType == SOCK_STREAM) //TCP
739 {
740 if(socket->bsdState != SKT_EST)
741 return SOCKET_ERROR;
742  
743 if(HandlePossibleTCPDisconnection(s))
744 return SOCKET_ERROR;
745  
746 return TCPGetArray(socket->SocketID, (BYTE*)buf, len);
747 }
748 else if(socket->SocketType == SOCK_DGRAM) //UDP
749 {
750 if(socket->bsdState != SKT_BOUND)
751 return SOCKET_ERROR;
752  
753 if(UDPIsGetReady(socket->SocketID))
754 return UDPGetArray((BYTE*)buf, len);
755 }
756  
757 return 0;
758 }
759  
760 /*****************************************************************************
761 Function:
762 int recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)
763  
764 Summary:
765 The recvfrom() function is used to receive incoming data that
766 has been queued for a socket.
767  
768 Description:
769 The recvfrom() function is used to receive incoming data that
770 has been queued for a socket. This function can be used with
771 both datagram and stream type sockets. If the available data
772 is too large to fit in the supplied application buffer buf,
773 excess bytes are discarded in case of SOCK_DGRAM type
774 sockets. For SOCK_STREAM types, the data is buffered
775 internally so the application can retreive all data by
776 multiple calls of recvfrom.
777  
778 Precondition:
779 socket function should be called.
780  
781 Parameters:
782 s - Socket descriptor returned from a previous call to socket.
783 buf - application data receive buffer.
784 len - buffer length in bytes.
785 flags - message flags. Currently this is not supported.
786 from - pointer to the sockaddr structure that will be
787 filled in with the destination address.
788 fromlen - size of buffer pointed by from.
789  
790 Returns:
791 If recvfrom is successful, the number of bytes copied to
792 application buffer buf is returned. A value of zero indicates
793 no data available. A return value of SOCKET_ERROR (-1)
794 indicates an error condition.
795  
796 Remarks:
797 None.
798 ***************************************************************************/
799 int recvfrom( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen )
800 {
801 struct BSDSocket *socket;
802 struct sockaddr_in *rem_addr;
803 SOCKET_INFO *remoteSockInfo;
804  
805 socket = &BSDSocketArray[s];
806 rem_addr = (struct sockaddr_in *)from;
807  
808 if(socket->SocketType == SOCK_DGRAM) //UDP
809 {
810 // If this BSD socket doesn't have a Microchip UDP socket associated
811 // with it yet, then no data can be received and we must not use the
812 // socket->SocketID parameter, which isn't set yet.
813 if(socket->bsdState != SKT_BOUND)
814 return 0;
815  
816 if(UDPIsGetReady(socket->SocketID))
817 {
818 // Capture sender information (can change packet to packet)
819 if(from && fromlen)
820 {
821 if((unsigned int)*fromlen >= sizeof(struct sockaddr_in))
822 {
823 rem_addr->sin_addr.S_un.S_addr = UDPSocketInfo[socket->SocketID].remoteNode.IPAddr.Val;
824 rem_addr->sin_port = UDPSocketInfo[socket->SocketID].remotePort;
825 *fromlen = sizeof(struct sockaddr_in);
826 }
827 }
828  
829 return UDPGetArray((BYTE*)buf, len);
830 }
831 }
832 else //TCP recieve from already connected socket.
833 {
834 if(from && fromlen)
835 {
836 // Capture sender information (will always match socket connection information)
837 if((unsigned int)*fromlen >= sizeof(struct sockaddr_in))
838 {
839 remoteSockInfo = TCPGetRemoteInfo(socket->SocketID);
840 rem_addr->sin_addr.S_un.S_addr = remoteSockInfo->remote.IPAddr.Val;
841 rem_addr->sin_port = remoteSockInfo->remotePort.Val;
842 *fromlen = sizeof(struct sockaddr_in);
843 }
844 }
845 return recv(s, buf, len, 0);
846 }
847 return 0;
848 }
849  
850 /*****************************************************************************
851 Function:
852 int gethostname(char* name, int namelen )
853  
854 Summary:
855 Returns the standard host name for the system.
856  
857 Description:
858 This function returns the standard host name of the system which is
859 calling this function. The returned name is null-terminated.
860  
861 Precondition:
862 None.
863  
864 Parameters:
865 name - Pointer to a buffer that receives the local host name.
866 namelen - size of the name array.
867  
868 Returns:
869 Success will return a value of 0.
870 If name is too short to hold the host name or any other error occurs,
871 SOCKET_ERROR (-1) will be returned. On error, *name will be unmodified
872 and no null terminator will be generated.
873  
874 Remarks:
875 None.
876 ***************************************************************************/
877 int gethostname(char* name, int namelen)
878 {
879 WORD wSourceLen;
880 WORD w;
881 BYTE v;
882  
883 wSourceLen = sizeof(AppConfig.NetBIOSName);
884 for(w = 0; w < wSourceLen; w++)
885 {
886 v = AppConfig.NetBIOSName[w];
887 if((v == ' ') || (v == 0u))
888 break;
889 }
890 wSourceLen = w;
891 if(namelen < (int)wSourceLen + 1)
892 return SOCKET_ERROR;
893  
894 memcpy((void*)name, (void*)AppConfig.NetBIOSName, wSourceLen);
895 name[wSourceLen] = 0;
896  
897 return 0;
898 }
899  
900 /*****************************************************************************
901 Function:
902 int closesocket( SOCKET s )
903  
904 Summary:
905 The closesocket function closes an existing socket.
906  
907 Description:
908 The closesocket function closes an existing socket.
909 This function releases the socket descriptor s.
910 Any data buffered at the socket is discarded. If the
911 socket s is no longer needed, closesocket() must be
912 called in order to release all resources associated with s.
913  
914 Precondition:
915 None.
916  
917 Parameters:
918 s - Socket descriptor returned from a previous call to socket
919  
920 Returns:
921 If closesocket is successful, a value of 0 is returned.
922 A return value of SOCKET_ERROR (-1) indicates an error.
923  
924 Remarks:
925 None.
926 ***************************************************************************/
927 int closesocket( SOCKET s )
928 {
929 BYTE i;
930 struct BSDSocket *socket;
931  
932 if( s >= BSD_SOCKET_COUNT )
933 return SOCKET_ERROR;
934  
935 socket = &BSDSocketArray[s];
936  
937 if(socket->bsdState == SKT_CLOSED)
938 return 0; // Nothing to do, so return success
939  
940 if(socket->SocketType == SOCK_STREAM)
941 {
942 if(socket->bsdState == SKT_BSD_LISTEN)
943 {
944 // This is a listerner handle, so when we close it we also should
945 // close all TCP sockets that were opened for backlog processing
946 // but didn't actually get connected
947 for(i = 0; i < sizeof(BSDSocketArray)/sizeof(BSDSocketArray[0]); i++)
948 {
949 if(BSDSocketArray[i].bsdState != SKT_LISTEN)
950 continue;
951 if(BSDSocketArray[i].localPort == socket->localPort)
952 {
953 TCPClose(BSDSocketArray[i].SocketID);
954 BSDSocketArray[i].bsdState = SKT_CLOSED;
955 }
956 }
957 }
958 else if(socket->bsdState >= SKT_LISTEN)
959 {
960 // For server sockets, if the parent listening socket is still open,
961 // then return this socket to the queue for future backlog processing.
962 if(socket->isServer)
963 {
964 for(i = 0; i < sizeof(BSDSocketArray)/sizeof(BSDSocketArray[0]); i++)
965 {
966 if(BSDSocketArray[i].bsdState != SKT_BSD_LISTEN)
967 continue;
968 if(BSDSocketArray[i].localPort == socket->localPort)
969 {
970 TCPDisconnect(socket->SocketID);
971  
972 // Listener socket is still open, so just return to the
973 // listening state so that the user must call accept() again to
974 // reuse this BSD socket
975 socket->bsdState = SKT_LISTEN;
976 return 0;
977 }
978 }
979 // If we get down here, then the parent listener socket has
980 // apparently already been closed, so this socket can not be
981 // reused. Close it complete.
982 TCPClose(socket->SocketID);
983 }
984 else if(socket->bsdState != SKT_DISCONNECTED) // this is a client socket that isn't already disconnected
985 {
986 TCPClose(socket->SocketID);
987 }
988 }
989 }
990 else //udp sockets
991 {
992 if(socket->bsdState == SKT_BOUND)
993 UDPClose(socket->SocketID);
994 }
995  
996 socket->bsdState = SKT_CLOSED;
997 return 0; //success
998 }
999  
1000  
1001 /*****************************************************************************
1002 Function:
1003 static BOOL HandlePossibleTCPDisconnection(SOCKET s)
1004  
1005 Summary:
1006 Internal function that checks for asynchronous TCP connection state
1007 changes and resynchs the BSD socket descriptor state to match.
1008  
1009 Description:
1010 Internal function that checks for asynchronous TCP connection state
1011 changes and resynchs the BSD socket descriptor state to match.
1012  
1013 Precondition:
1014 None
1015  
1016 Parameters:
1017 s - TCP type socket descriptor returned from a previous call to socket.
1018 This socket must be in the SKT_LISTEN, SKT_IN_PROGRESS, SKT_EST, or
1019 SKT_DISCONNECTED states.
1020  
1021 Returns:
1022 TRUE - Socket is disconnected
1023 FALSE - Socket is
1024  
1025 ***************************************************************************/
1026 static BOOL HandlePossibleTCPDisconnection(SOCKET s)
1027 {
1028 struct BSDSocket *socket;
1029 BYTE i;
1030 BOOL bSocketWasReset;
1031  
1032 socket = &BSDSocketArray[s];
1033  
1034 // Nothing to do if disconnection has already been handled
1035 if(socket->bsdState == SKT_DISCONNECTED)
1036 return TRUE;
1037  
1038 // Find out if a disconnect has occurred
1039 bSocketWasReset = TCPWasReset(socket->SocketID);
1040  
1041 // For server sockets, if the parent listening socket is still open,
1042 // then return this socket to the queue for future backlog processing.
1043 if(socket->isServer)
1044 {
1045 for(i = 0; i < sizeof(BSDSocketArray)/sizeof(BSDSocketArray[0]); i++)
1046 {
1047 if(BSDSocketArray[i].bsdState != SKT_BSD_LISTEN)
1048 continue;
1049 if(BSDSocketArray[i].localPort == socket->localPort)
1050 {
1051 // Nothing to do if a disconnect has not occurred
1052 if(!bSocketWasReset)
1053 return FALSE;
1054  
1055 // Listener socket is still open, so just return to the
1056 // listening state so that the user must call accept() again to
1057 // reuse this BSD socket
1058 socket->bsdState = SKT_LISTEN;
1059 return TRUE;
1060 }
1061 }
1062 }
1063  
1064 // If we get down here and the socket was reset, then this socket
1065 // should be closed so that no more clients can connect to it. However,
1066 // we can't go to the BSD SKT_CLOSED state directly since the user still
1067 // has to call closesocket() with this s SOCKET descriptor first.
1068 if(bSocketWasReset)
1069 {
1070 TCPClose(socket->SocketID);
1071 socket->bsdState = SKT_DISCONNECTED;
1072 return TRUE;
1073 }
1074  
1075 return FALSE;
1076 }
1077  
1078 #endif //STACK_USE_BERKELEY_API
1079  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3