OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_webserver/] [sock.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * sock.c -- Posix Socket upper layer support module for general posix use
3
 *
4
 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
5
 */
6
 
7
/******************************** Description *********************************/
8
 
9
/*
10
 *      Posix Socket Module.  This supports blocking and non-blocking buffered
11
 *      socket I/O.
12
 */
13
 
14
/********************************** Includes **********************************/
15
 
16
#include        <string.h>
17
#include        <stdlib.h>
18
 
19
#if UEMF
20
        #include        "uemf.h"
21
#else
22
        #include        <socket.h>
23
        #include        <types.h>
24
        #include        <unistd.h>
25
        #include        "emfInternal.h"
26
#endif
27
 
28
/************************************ Locals **********************************/
29
 
30
socket_t        **socketList;                   /* List of open sockets */
31
int                     socketMax;                              /* Maximum size of socket */
32
int                     socketHighestFd = -1;   /* Highest socket fd opened */
33
 
34
/***************************** Forward Declarations ***************************/
35
 
36
static int      socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode);
37
static int      tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
38
                        struct sockaddr *server);
39
 
40
/*********************************** Code *************************************/
41
/*
42
 *      Write to a socket. Absorb as much data as the socket can buffer. Block if
43
 *      the socket is in blocking mode. Returns -1 on error, otherwise the number
44
 *      of bytes written.
45
 */
46
 
47
int     socketWrite(int sid, char *buf, int bufsize)
48
{
49
        socket_t        *sp;
50
        ringq_t         *rq;
51
        int                     len, bytesWritten, room;
52
 
53
        a_assert(buf);
54
        a_assert(bufsize >= 0);
55
 
56
        if ((sp = socketPtr(sid)) == NULL) {
57
                return -1;
58
        }
59
 
60
/*
61
 *      Loop adding as much data to the output ringq as we can absorb. Initiate a
62
 *      flush when the ringq is too full and continue. Block in socketFlush if the
63
 *      socket is in blocking mode.
64
 */
65
        rq = &sp->outBuf;
66
        for (bytesWritten = 0; bufsize > 0; ) {
67
                if ((room = ringqPutBlkMax(rq)) == 0) {
68
                        if (socketFlush(sid) < 0) {
69
                                return -1;
70
                        }
71
                        if ((room = ringqPutBlkMax(rq)) == 0) {
72
                                if (sp->flags & SOCKET_BLOCK) {
73
#if WIN || CE
74
                                        int             errCode;
75
                                        if (! socketWaitForEvent(sp,  FD_WRITE | SOCKET_WRITABLE,
76
                                                &errCode)) {
77
                                                return -1;
78
                                        }
79
#endif
80
                                        continue;
81
                                }
82
                                break;
83
                        }
84
                        continue;
85
                }
86
                len = min(room, bufsize);
87
                ringqPutBlk(rq, (unsigned char *) buf, len);
88
                bytesWritten += len;
89
                bufsize -= len;
90
                buf += len;
91
        }
92
        return bytesWritten;
93
}
94
 
95
/******************************************************************************/
96
/*
97
 *      Write a string to a socket
98
 */
99
 
100
int     socketWriteString(int sid, char_t *buf)
101
{
102
 #if UNICODE
103
        char    *byteBuf;
104
        int             r, len;
105
 
106
        len = gstrlen(buf);
107
        byteBuf = ballocUniToAsc(buf, len);
108
        r = socketWrite(sid, byteBuf, len);
109
        bfreeSafe(B_L, byteBuf);
110
        return r;
111
 #else
112
        return socketWrite(sid, buf, strlen(buf));
113
 #endif /* UNICODE */
114
}
115
 
116
/******************************************************************************/
117
/*
118
 *      Read from a socket. Return the number of bytes read if successful. This
119
 *      may be less than the requested "bufsize" and may be zero. Return -1 for
120
 *      errors. Return 0 for EOF. Otherwise return the number of bytes read.
121
 *      If this routine returns zero it indicates an EOF condition.
122
 *  which can be verified with socketEof()
123
 
124
 *      Note: this ignores the line buffer, so a previous socketGets
125
 *      which read a partial line may cause a subsequent socketRead to miss some
126
 *      data. This routine may block if the socket is in blocking mode.
127
 *
128
 */
129
 
130
int     socketRead(int sid, char *buf, int bufsize)
131
{
132
        socket_t        *sp;
133
        ringq_t         *rq;
134
        int                     len, room, errCode, bytesRead;
135
 
136
        a_assert(buf);
137
        a_assert(bufsize > 0);
138
 
139
        if ((sp = socketPtr(sid)) == NULL) {
140
                return -1;
141
        }
142
 
143
        if (sp->flags & SOCKET_EOF) {
144
                return 0;
145
        }
146
 
147
        rq = &sp->inBuf;
148
        for (bytesRead = 0; bufsize > 0; ) {
149
                len = min(ringqLen(rq), bufsize);
150
                if (len <= 0) {
151
/*
152
 *                      if blocking mode and already have data, exit now or it may block
153
 *                      forever.
154
 */
155
                        if ((sp->flags & SOCKET_BLOCK) &&
156
                                (bytesRead > 0)) {
157
                                break;
158
                        }
159
/*
160
 *                      This flush is critical for readers of datagram packets. If the
161
 *                      buffer is not big enough to read the whole datagram in one hit,
162
 *                      the recvfrom call will fail.
163
 */
164
                        ringqFlush(rq);
165
                        room = ringqPutBlkMax(rq);
166
                        len = socketGetInput(sid, (char *) rq->endp, room, &errCode);
167
                        if (len < 0) {
168
                                if (errCode == EWOULDBLOCK) {
169
                                        if ((sp->flags & SOCKET_BLOCK) &&
170
                                                (bytesRead ==  0)) {
171
                                                continue;
172
                                        }
173
                                        if (bytesRead >= 0) {
174
                                                return bytesRead;
175
                                        }
176
                                }
177
                                return -1;
178
 
179
                        } else if (len == 0) {
180
/*
181
 *                              If bytesRead is 0, this is EOF since socketRead should never
182
 *                              be called unless there is data yet to be read.  Set the flag.
183
 *                              Then pass back the number of bytes read.
184
 */
185
                                if (bytesRead == 0) {
186
                                        sp->flags |= SOCKET_EOF;
187
                                }
188
                                return bytesRead;
189
                        }
190
                        ringqPutBlkAdj(rq, len);
191
                        len = min(len, bufsize);
192
                }
193
                memcpy(&buf[bytesRead], rq->servp, len);
194
                ringqGetBlkAdj(rq, len);
195
                bufsize -= len;
196
                bytesRead += len;
197
        }
198
        return bytesRead;
199
}
200
 
201
/******************************************************************************/
202
/*
203
 *      Get a string from a socket. This returns data in *buf in a malloced string
204
 *      after trimming the '\n'. If there is zero bytes returned, *buf will be set
205
 *      to NULL. If doing non-blocking I/O, it returns -1 for error, EOF or when
206
 *      no complete line yet read. If doing blocking I/O, it will block until an
207
 *      entire line is read. If a partial line is read socketInputBuffered or
208
 *      socketEof can be used to distinguish between EOF and partial line still
209
 *      buffered. This routine eats and ignores carriage returns.
210
 */
211
 
212
int     socketGets(int sid, char_t **buf)
213
{
214
        socket_t        *sp;
215
        ringq_t         *lq;
216
        char            c;
217
        int                     rc, len;
218
 
219
        a_assert(buf);
220
        *buf = NULL;
221
 
222
        if ((sp = socketPtr(sid)) == NULL) {
223
                return -1;
224
        }
225
        lq = &sp->lineBuf;
226
 
227
        while (1) {
228
 
229
                if ((rc = socketRead(sid, &c, 1)) < 0) {
230
                        return rc;
231
                }
232
 
233
                if (rc == 0) {
234
/*
235
 *                      If there is a partial line and we are at EOF, pretend we saw a '\n'
236
 */
237
                        if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
238
                                c = '\n';
239
                        } else {
240
                                return -1;
241
                        }
242
                }
243
/*
244
 *              If a newline is seen, return the data excluding the new line to the
245
 *              caller. If carriage return is seen, just eat it.
246
 */
247
                if (c == '\n') {
248
                        len = ringqLen(lq);
249
                        if (len > 0) {
250
                                *buf = ballocAscToUni(lq->servp, len);
251
                        } else {
252
                                *buf = NULL;
253
                        }
254
                        ringqFlush(lq);
255
                        return len;
256
 
257
                } else if (c == '\r') {
258
                        continue;
259
                }
260
                ringqPutcA(lq, c);
261
        }
262
        return 0;
263
}
264
 
265
/******************************************************************************/
266
/*
267
 *      Flush the socket. Block if the socket is in blocking mode.
268
 *      This will return -1 on errors and 0 if successful.
269
 */
270
 
271
int socketFlush(int sid)
272
{
273
        socket_t        *sp;
274
        ringq_t         *rq;
275
        int                     len, bytesWritten, errCode;
276
 
277
        if ((sp = socketPtr(sid)) == NULL) {
278
                return -1;
279
        }
280
        rq = &sp->outBuf;
281
 
282
/*
283
 *      Set the background flushing flag which socketEventProc will check to
284
 *      continue the flush.
285
 */
286
        if (! (sp->flags & SOCKET_BLOCK)) {
287
                sp->flags |= SOCKET_FLUSHING;
288
        }
289
 
290
/*
291
 *      Break from loop if not blocking after initiating output. If we are blocking
292
 *      we wait for a write event.
293
 */
294
        while (ringqLen(rq) > 0) {
295
                len = ringqGetBlkMax(&sp->outBuf);
296
                bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
297
                if (bytesWritten < 0) {
298
                        if (errCode == EINTR) {
299
                                continue;
300
                        } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
301
#if WIN || CE
302
                                if (sp->flags & SOCKET_BLOCK) {
303
                                        int             errCode;
304
                                        if (! socketWaitForEvent(sp,  FD_WRITE | SOCKET_WRITABLE,
305
                                                &errCode)) {
306
                                                return -1;
307
                                        }
308
                                        continue;
309
                                }
310
#endif
311
/*
312
 *                              Ensure we get a FD_WRITE message when the socket can absorb
313
 *                              more data (non-blocking only.) Store the user's mask if we
314
 *                              haven't done it already.
315
 */
316
                                if (sp->saveMask < 0 ) {
317
                                        sp->saveMask = sp->handlerMask;
318
                                        socketRegisterInterest(sp,
319
                                        sp->handlerMask | SOCKET_WRITABLE);
320
                                }
321
                                return 0;
322
                        }
323
                        return -1;
324
                }
325
                ringqGetBlkAdj(rq, bytesWritten);
326
        }
327
/*
328
 *      If the buffer is empty, reset the ringq pointers to point to the start
329
 *      of the buffer. This is essential to ensure that datagrams get written
330
 *      in one single I/O operation.
331
 */
332
        if (ringqLen(rq) == 0) {
333
                ringqFlush(rq);
334
        }
335
/*
336
 *      Restore the users mask if it was saved by the non-blocking code above.
337
 *      Note: saveMask = -1 if empty. socketRegisterInterest will set handlerMask
338
 */
339
        if (sp->saveMask >= 0) {
340
                socketRegisterInterest(sp, sp->saveMask);
341
                sp->saveMask = -1;
342
        }
343
        sp->flags &= ~SOCKET_FLUSHING;
344
        return 0;
345
}
346
 
347
/******************************************************************************/
348
/*
349
 *      Return the count of input characters buffered. We look at both the line
350
 *      buffer and the input (raw) buffer. Return -1 on error or EOF.
351
 */
352
 
353
int socketInputBuffered(int sid)
354
{
355
        socket_t        *sp;
356
 
357
        if ((sp = socketPtr(sid)) == NULL) {
358
                return -1;
359
        }
360
        if (socketEof(sid)) {
361
                return -1;
362
        }
363
        return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
364
}
365
 
366
/******************************************************************************/
367
/*
368
 *      Return true if EOF
369
 */
370
 
371
int socketEof(int sid)
372
{
373
        socket_t        *sp;
374
 
375
        if ((sp = socketPtr(sid)) == NULL) {
376
                return -1;
377
        }
378
        return sp->flags & SOCKET_EOF;
379
}
380
 
381
/******************************************************************************/
382
/*
383
 *      Return the number of bytes the socket can absorb without blocking
384
 */
385
 
386
int socketCanWrite(int sid)
387
{
388
        socket_t        *sp;
389
 
390
        if ((sp = socketPtr(sid)) == NULL) {
391
                return -1;
392
        }
393
        return sp->outBuf.buflen - ringqLen(&sp->outBuf) - 1;
394
}
395
 
396
/******************************************************************************/
397
/*
398
 *      Add one to allow the user to write exactly SOCKET_BUFSIZ
399
 */
400
 
401
void socketSetBufferSize(int sid, int in, int line, int out)
402
{
403
        socket_t        *sp;
404
 
405
        if ((sp = socketPtr(sid)) == NULL) {
406
                return;
407
        }
408
 
409
        if (in >= 0) {
410
                ringqClose(&sp->inBuf);
411
                in++;
412
                ringqOpen(&sp->inBuf, in, in);
413
        }
414
 
415
        if (line >= 0) {
416
                ringqClose(&sp->lineBuf);
417
                line++;
418
                ringqOpen(&sp->lineBuf, line, line);
419
        }
420
 
421
        if (out >= 0) {
422
                ringqClose(&sp->outBuf);
423
                out++;
424
                ringqOpen(&sp->outBuf, out, out);
425
        }
426
}
427
 
428
/******************************************************************************/
429
/*
430
 *      Create a user handler for this socket. The handler called whenever there
431
 *      is an event of interest as defined by handlerMask (SOCKET_READABLE, ...)
432
 */
433
 
434
void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler,
435
                int data)
436
{
437
        socket_t        *sp;
438
 
439
        if ((sp = socketPtr(sid)) == NULL) {
440
                return;
441
        }
442
        sp->handler = handler;
443
        sp->handler_data = data;
444
        socketRegisterInterest(sp, handlerMask);
445
}
446
 
447
/******************************************************************************/
448
/*
449
 *      Delete a handler
450
 */
451
 
452
void socketDeleteHandler(int sid)
453
{
454
        socket_t        *sp;
455
 
456
        if ((sp = socketPtr(sid)) == NULL) {
457
                return;
458
        }
459
        sp->handler = NULL;
460
        socketRegisterInterest(sp, 0);
461
}
462
 
463
/******************************************************************************/
464
/*
465
 *      Socket output procedure. Return -1 on errors otherwise return the number
466
 *      of bytes written.
467
 */
468
 
469
static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode)
470
{
471
        struct sockaddr_in      server;
472
        int                                     bytes;
473
 
474
        a_assert(sp);
475
        a_assert(buf);
476
        a_assert(toWrite > 0);
477
        a_assert(errCode);
478
 
479
        *errCode = 0;
480
 
481
#if WIN || CE
482
        if ((sp->flags & SOCKET_ASYNC)
483
                        && ! socketWaitForEvent(sp,  FD_CONNECT, errCode)) {
484
                return -1;
485
        }
486
#endif
487
 
488
/*
489
 *      Write the data
490
 */
491
        if (sp->flags & SOCKET_BROADCAST) {
492
                server.sin_family = AF_INET;
493
#if UEMF || LITTLEFOOT
494
                server.sin_addr.s_addr = INADDR_BROADCAST;
495
#else
496
                server.sin_addr.s_addr = inet_addr(basicGetBroadcastAddress());
497
#endif
498
                server.sin_port = htons((short)(sp->port & 0xFFFF));
499
                if ((bytes = sendto(sp->sock, buf, toWrite, 0,
500
                        (struct sockaddr *) &server, sizeof(server))) < 0) {
501
                        bytes = tryAlternateSendTo(sp->sock, buf, toWrite, 0,
502
                        (struct sockaddr *) &server);
503
                }
504
        } else if (sp->flags & SOCKET_DATAGRAM) {
505
                server.sin_family = AF_INET;
506
                server.sin_addr.s_addr = inet_addr(sp->host);
507
                server.sin_port = htons((short)(sp->port & 0xFFFF));
508
                bytes = sendto(sp->sock, buf, toWrite, 0,
509
                        (struct sockaddr *) &server, sizeof(server));
510
 
511
        } else {
512
                bytes = send(sp->sock, buf, toWrite, 0);
513
        }
514
 
515
        if (bytes < 0) {
516
                *errCode = socketGetError();
517
#if WIN || CE 
518
                sp->currentEvents &= ~FD_WRITE;
519
#endif
520
 
521
                return -1;
522
 
523
        } else if (bytes == 0 && bytes != toWrite) {
524
                *errCode = EWOULDBLOCK;
525
#if WIN || CE
526
                sp->currentEvents &= ~FD_WRITE;
527
#endif
528
                return -1;
529
        }
530
 
531
/*
532
 *      Ensure we get to write some more data real soon if the socket can absorb
533
 *      more data
534
 */
535
#if !UEMF
536
#if WIN 
537
        if (sp->interestEvents & FD_WRITE) {
538
                emfTime_t blockTime = { 0, 0 };
539
                emfSetMaxBlockTime(&blockTime);
540
        }
541
#endif /* WIN */
542
#endif
543
        return bytes;
544
}
545
 
546
/******************************************************************************/
547
/*
548
 *              If the sendto failed, swap the first two bytes in the
549
 *              sockaddr structure.  This is a kludge due to a change in
550
 *              VxWorks between versions 5.3 and 5.4, but we want the
551
 *              product to run on either.
552
 */
553
static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
554
                        struct sockaddr *server)
555
{
556
#if VXWORKS
557
        char *ptr;
558
 
559
        ptr = (char *)server;
560
        *ptr = *(ptr+1);
561
        *(ptr+1) = 0;
562
        return sendto(sock, buf, toWrite, i, server, sizeof(struct sockaddr));
563
#else
564
        return -1;
565
#endif /* VXWORKS */
566
}
567
 
568
/******************************************************************************/
569
/*
570
 *      Allocate a new socket structure
571
 */
572
 
573
int socketAlloc(char *host, int port, socketAccept_t accept, int flags)
574
{
575
        socket_t        *sp;
576
        int                     sid;
577
 
578
        if ((sid = hAllocEntry((void***) &socketList, &socketMax,
579
                        sizeof(socket_t))) < 0) {
580
                return -1;
581
        }
582
        sp = socketList[sid];
583
 
584
        sp->sid = sid;
585
        sp->accept = accept;
586
        sp->port = port;
587
        sp->fileHandle = -1;
588
        sp->saveMask = -1;
589
 
590
        if (host) {
591
                strncpy(sp->host, host, sizeof(sp->host));
592
        }
593
 
594
/*
595
 *      Preserve only specified flags from the callers open
596
 */
597
        a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK|
598
                                                SOCKET_LISTENING)) == 0);
599
        sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK|
600
                                                SOCKET_LISTENING);
601
 
602
/*
603
 *      Add one to allow the user to write exactly SOCKET_BUFSIZ
604
 */
605
        ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
606
        ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1);
607
        ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
608
 
609
        return sid;
610
}
611
 
612
/******************************************************************************/
613
/*
614
 *      Free a socket structure
615
 */
616
 
617
void socketFree(int sid)
618
{
619
        socket_t        *sp;
620
        char_t          buf[256];
621
        int                     i;
622
 
623
        if ((sp = socketPtr(sid)) == NULL) {
624
                return;
625
        }
626
 
627
/*
628
 *      To close a socket, remove any registered interests, set it to
629
 *      non-blocking so that the recv which follows won't block, do a
630
 *      shutdown on it so peers on the other end will receive a FIN,
631
 *      then read any data not yet retrieved from the receive buffer,
632
 *      and finally close it.  If these steps are not all performed
633
 *      RESETs may be sent to the other end causing problems.
634
 */
635
        socketRegisterInterest(sp, 0);
636
        if (sp->sock >= 0) {
637
                socketSetBlock(sid, 0);
638
                if (shutdown(sp->sock, 1) >= 0) {
639
                        recv(sp->sock, buf, sizeof(buf), 0);
640
                }
641
#if WIN || CE
642
                closesocket(sp->sock);
643
#else
644
                close(sp->sock);
645
#endif
646
        }
647
 
648
        ringqClose(&sp->inBuf);
649
        ringqClose(&sp->outBuf);
650
        ringqClose(&sp->lineBuf);
651
 
652
        bfree(B_L, sp);
653
        socketMax = hFree((void***) &socketList, sid);
654
 
655
/*
656
 *      Calculate the new highest socket number
657
 */
658
        socketHighestFd = -1;
659
        for (i = 0; i < socketMax; i++) {
660
                if ((sp = socketList[i]) == NULL) {
661
                        continue;
662
                }
663
                socketHighestFd = max(socketHighestFd, sp->sock);
664
        }
665
}
666
 
667
/******************************************************************************/
668
/*
669
 *      Validate a socket handle
670
 */
671
 
672
socket_t *socketPtr(int sid)
673
{
674
        if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
675
                a_assert(NULL);
676
                errno = EBADF;
677
                return NULL;
678
        }
679
 
680
        a_assert(socketList[sid]);
681
        return socketList[sid];
682
}
683
 
684
/******************************************************************************/
685
/*
686
 *      Get the operating system error code
687
 */
688
 
689
int socketGetError()
690
{
691
#if WIN || CE
692
        switch (WSAGetLastError()) {
693
        case WSAEWOULDBLOCK:
694
                return EWOULDBLOCK;
695
        case WSAECONNRESET:
696
                return ECONNRESET;
697
        case WSAENETDOWN:
698
                return ENETDOWN;
699
        case WSAEPROCLIM:
700
                return EAGAIN;
701
        case WSAEINTR:
702
                return EINTR;
703
        default:
704
                return EINVAL;
705
        }
706
#else
707
        return errno;
708
#endif
709
}
710
 
711
/******************************************************************************/
712
/*
713
 *      Return the underlying socket handle
714
 */
715
 
716
int socketGetHandle(int sid)
717
{
718
        socket_t        *sp;
719
 
720
        if ((sp = socketPtr(sid)) == NULL) {
721
                return -1;
722
        }
723
        return sp->sock;
724
}
725
 
726
/******************************************************************************/
727
/*
728
 *      Get blocking mode
729
 */
730
 
731
int socketGetBlock(int sid)
732
{
733
        socket_t        *sp;
734
 
735
        if ((sp = socketPtr(sid)) == NULL) {
736
                a_assert(0);
737
                return 0;
738
        }
739
        return (sp->flags & SOCKET_BLOCK);
740
}
741
 
742
/******************************************************************************/
743
/*
744
 *      Get mode
745
 */
746
 
747
int socketGetMode(int sid)
748
{
749
        socket_t        *sp;
750
 
751
        if ((sp = socketPtr(sid)) == NULL) {
752
                a_assert(0);
753
                return 0;
754
        }
755
        return sp->flags;
756
}
757
 
758
/******************************************************************************/
759
/*
760
 *      Set mode
761
 */
762
 
763
void socketSetMode(int sid, int mode)
764
{
765
        socket_t        *sp;
766
 
767
        if ((sp = socketPtr(sid)) == NULL) {
768
                a_assert(0);
769
                return;
770
        }
771
        sp->flags = mode;
772
}
773
 
774
/******************************************************************************/
775
/*
776
 *      Get port.
777
 */
778
 
779
int socketGetPort(int sid)
780
{
781
        socket_t        *sp;
782
 
783
        if ((sp = socketPtr(sid)) == NULL) {
784
                return -1;
785
        }
786
        return sp->port;
787
}
788
 
789
/******************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.