Annotation of kernel/kern/netport_tcp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1989 Carnegie-Mellon University
                     28:  * Copyright (c) 1988 Carnegie-Mellon University
                     29:  * Copyright (c) 1987 Carnegie-Mellon University
                     30:  * All rights reserved.  The CMU software License Agreement specifies
                     31:  * the terms and conditions for use and redistribution.
                     32:  */
                     33: /*
                     34:  * File:       netport_tcp.c
                     35:  * Purpose:
                     36:  *     Front-end to the TCP system for the netport system
                     37:  *     implementing network IPC in the kernel.
                     38:  */
                     39: 
                     40: /*
                     41:  * This module is copied from the TCP tranport module of the user-state
                     42:  * network server, with only a minimum of changes.
                     43:  */
                     44: 
                     45: #import <sys/types.h>
                     46: #import <sys/socket.h>
                     47: #import <sys/socketvar.h>
                     48: #import <netinet/in.h>
                     49: #import <mach/kern_return.h>
                     50: #import <mach/port.h>
                     51: #import <kern/queue.h>
                     52: #import <kern/lock.h>
                     53: #import <kern/thread.h>
                     54: #import <kern/task.h>
                     55: #import <kern/ipc_netport.h>
                     56: #import <kern/kern_msg.h>
                     57: #import <kern/zalloc.h>
                     58: #import <sys/param.h>
                     59: #import <kern/xpr.h>
                     60: #import <mach/vm_param.h>
                     61: 
                     62: #ifndef        NULL
                     63: #define NULL   0
                     64: #endif NULL
                     65: 
                     66: #if    NeXT
                     67: #define        Debugger(s)     panic(s)
                     68: #define queue_enter_first      queue_enter_head
                     69: #else  NeXT
                     70: #define        Debugger(s)     kdb_kintr()
                     71: #endif NeXT
                     72: 
                     73: /*
                     74:  * Definitions for compatibility with the network server coding conventions
                     75:  * and debugging mechanism.
                     76:  */
                     77: #define PRIVATE                /**/
                     78: #define PUBLIC         /**/
                     79: #define EXPORT         /**/
                     80: #define BEGIN(name)    {
                     81: #define END            }
                     82: #define RETURN(val)    return (val)
                     83: #define RET            return
                     84: 
                     85: #define DEBUG0(a,b,c)                  XPR(XPR_NPTCP,(c,0,0,0,0,0))
                     86: #define DEBUG1(a,b,c,p1)               XPR(XPR_NPTCP,(c,p1,0,0,0,0))
                     87: #define DEBUG2(a,b,c,p1,p2)            XPR(XPR_NPTCP,(c,p1,p2,0,0,0))
                     88: #define DEBUG3(a,b,c,p1,p2,p3)         XPR(XPR_NPTCP,(c,p1,p2,p3,0,0))
                     89: #define DEBUG4(a,b,c,p1,p2,p3,p4)      XPR(XPR_NPTCP,(c,p1,p2,p3,p4,0))
                     90: #define DEBUG5(a,b,c,p1,p2,p3,p4,p5)   XPR(XPR_NPTCP,(c,p1,p2,p3,p4,p5))
                     91: #define DEBUG6(a,b,c,p1,p2,p3,p4,p5,p6)        XPR(XPR_NPTCP,(c,p1,p2,p3,p4,p5))
                     92: 
                     93: #define INCSTAT(s)                             /**/
                     94: #define msg            np_msg
                     95: #define errno          np_errno
                     96: #define ERROR(fmt)     {                       \
                     97:        np_printf fmt;                          \
                     98:        if (np_flags & NP_DEBUG)                \
                     99:                Debugger("NP");                 \
                    100: }
                    101: static char            np_msg[200];
                    102: static int             np_errno;
                    103: 
                    104: 
                    105: #define mutex                  slock
                    106: #define mutex_lock(l)          simple_lock(l)
                    107: #define mutex_unlock(l)                simple_unlock(l)
                    108: #define mutex_init(l)          simple_lock_init(l)
                    109: 
                    110: typedef int                    kern_cond_t;
                    111: #define condition_init(c)      /**/
                    112: #define condition_wait(c,l)    {       \
                    113:        simple_unlock(l);               \
                    114:        sleep((caddr_t)c,PZERO+1);      \
                    115:        simple_lock(l);                 \
                    116: }
                    117: #define condition_signal(c)    wakeup((caddr_t)c)
                    118: 
                    119: #if    NeXT
                    120: #else  NeXT
                    121: extern task_t  first_task;
                    122: #endif NeXT
                    123: 
                    124: /*
                    125:  * Macros to derive a TCP connection ID from a trid obtained from a client 
                    126:  * and vice-versa.
                    127:  */
                    128: #define SET_TCPID(tcpid,trid)  { (tcpid) = (trid).v1; }
                    129: #define SET_TRID(trid,tcpid)   { (trid).v1 = (tcpid); }
                    130: 
                    131: 
                    132: /*
                    133:  * Transaction records.
                    134:  */
                    135: typedef struct tcp_trans {
                    136:        int                     state;  /* see defines below */
                    137:        unsigned long           trid;
                    138:        int                     client_id;
                    139:        kern_msg_t              kmsg;
                    140:        int                     len;
                    141:        int                     crypt_level;
                    142: /*     int                     (*reply_proc)(); */
                    143:        queue_chain_t   transq; /* list of pending/waiting transactions */
                    144: } tcp_trans_t, *tcp_trans_ptr_t;
                    145: 
                    146: #define TCP_TR_INVALID 0
                    147: #define TCP_TR_PENDING 1       /* awaiting a reply */
                    148: #define TCP_TR_WAITING 2       /* awaiting transmission */
                    149: 
                    150: zone_t tcp_trans_zone;
                    151: 
                    152: 
                    153: 
                    154: /*
                    155:  * Forward declarations.
                    156:  */
                    157: void   np_tcp_conn_handler();
                    158: 
                    159: 
                    160: /*
                    161:  * TCP port to be used by the Mach netport service.
                    162:  */
                    163: #define TCP_NETMSG_PORT        2454
                    164: 
                    165: 
                    166: /*
                    167:  * Debugging flags.
                    168:  */
                    169: #define TCP_DBG_MAJOR  (0x1)   /* major events */
                    170: #define TCP_DBG_CRASH  (0x2)   /* host crashes */
                    171: #define TCP_DBG_VERBOSE        (0x4)   /* verbose output */
                    172: 
                    173: /*
                    174:  * Connection records.
                    175:  */
                    176: typedef        struct tcp_conn {
                    177:        int                     state;  /* see defines below */
                    178:        struct socket           *sock;  /* socket structure */
                    179:        thread_t                th;     /* service thread */
                    180:        struct mutex            lock;   /* lock for this record */
                    181:        kern_cond_t             cond;   /* to wake up the service thread */
                    182:        netaddr_t               dest;   /* peer for current connection */
                    183:        queue_head_t    trans;  /* list of pending/waiting transactions */
                    184:        int                     count;  /* number of pending/waiting trans */
                    185:        queue_chain_t   connq;  /* list of records */
                    186:        unsigned long           incarn; /* incarnation number */
                    187:        tcp_ctl_t               ctlbuf; /* for xmit control header */
                    188: } tcp_conn_t, *tcp_conn_ptr_t;
                    189: 
                    190: #define TCP_INVALID    0
                    191: #define TCP_FREE       1
                    192: #define TCP_CONNECTED  2
                    193: #define TCP_OPENING    3
                    194: #define TCP_CLOSING    4
                    195: #define TCP_CLOSED     5
                    196: 
                    197: /*
                    198:  * Static declarations.
                    199:  */
                    200: PRIVATE tcp_conn_t             conn_vec[32];   /* connection records */
                    201: 
                    202: PRIVATE queue_head_t   conn_lru;       /* LRU list of active conn */
                    203: PRIVATE int                    conn_num;       /* number of active conn */
                    204: PRIVATE queue_head_t   conn_free;      /* list of free conn */
                    205: PRIVATE kern_cond_t    conn_cond;      /* to wake up listener */
                    206: PRIVATE int                    conn_closing;   /* number of conn in TCP_CLOSING */
                    207: PRIVATE struct mutex           conn_lock;      /* lock for conn_lru & conn_free */
                    208: 
                    209: 
                    210: /*
                    211:  * Transport IDs are composed of 16 bits for the client side and 16 bits
                    212:  * for the server side. The client side is just a counter, to be matched
                    213:  * between the message and the transaction record. The server side is composed
                    214:  * of 8 bits of index of the connection record in the conn_vec array and
                    215:  * 8 bits of incarnation number for this connection record.
                    216:  *
                    217:  * We can afford not to protect the counter for client-side IDs with a lock,
                    218:  * because transaction records for one connection are protected by the lock
                    219:  * that connection, and they never move from one connection to another.
                    220:  *
                    221:  * XXX This is not completely foolproof if there is A LOT of traffic,
                    222:  * but it's cheap.
                    223:  */
                    224: PRIVATE unsigned long                  trid_counter;
                    225: #define cptoix(cp)                     (((cp) - conn_vec)/sizeof(tcp_conn_t))
                    226: #define ixtocp(id)                     ((tcp_conn_ptr_t)&(conn_vec[(id)]))
                    227: #define TRID_SET_CLIENT(trid)          { trid = (trid_counter++) & 0xffff; }
                    228: #define TRID_GET_CLIENT(trid,cl)       { (cl) = (trid) & 0xffff; }
                    229: #define TRID_SET_SERVER(trid,sv)       { (trid) |= \
                    230:                                        (cptoix(sv) << 24) | ((sv)->incarn << 16);}
                    231: #define TRID_GET_SERVER(trid,sv)       { (sv) = ixtocp((trid) >> 24); \
                    232:                if ((((trid) >> 16) & 0xff) != (sv)->incarn) (sv) = NULL; }
                    233: 
                    234: 
                    235: 
                    236: /*
                    237:  * Limits on connected sockets.
                    238:  */
                    239: #define TCP_CONN_STEADY                6       /* steady-state max [6] */
                    240: #define TCP_CONN_OPENING       8       /* max open/opening [8] */
                    241: #define TCP_CONN_MAX           10      /* absolute maximum [10] */
                    242: 
                    243: 
                    244: /*
                    245:  * Zone for kmsg's to be used for incoming messages.
                    246:  */
                    247: extern zone_t  netport_kmsg_zone;
                    248: #define DATA_SIZE_MAX                          \
                    249:                (NETPORT_MSG_SIZE_MAX           \
                    250:                - sizeof(struct KMsg)           \
                    251:                + sizeof(tcp_ctl_t)             \
                    252:                + sizeof(ipc_network_hdr_t)     \
                    253:                + sizeof(msg_header_t))
                    254: 
                    255: 
                    256: 
                    257: /*
                    258:  * Macro for transmission of a simple control message.
                    259:  *
                    260:  * cp->lock must be held throughout.
                    261:  */
                    262: #define tcp_xmit_control(cp,ctlcode,a_trid,a_code,ret) {       \
                    263:        int     b_len;                                          \
                    264:                                                                \
                    265:        (cp)->ctlbuf.ctl = htonl(ctlcode);                      \
                    266:        (cp)->ctlbuf.trid = htonl(a_trid);                      \
                    267:        (cp)->ctlbuf.code = htonl(a_code);                      \
                    268:        (cp)->ctlbuf.size = 0;                                  \
                    269:        (cp)->ctlbuf.crypt_level = 0;                           \
                    270:        b_len = sizeof(tcp_ctl_t);                              \
                    271:        ret = mach_tcp_send(PORT_NULL,(cp)->sock,               \
                    272:                                &((cp)->ctlbuf),&b_len,0);      \
                    273:        INCSTAT(tcp_send);                                      \
                    274:        DEBUG6(TCP_DBG_VERBOSE,0,2803,cp,ctlcode,a_trid,        \
                    275:                                        a_code,ret,errno);      \
                    276: }
                    277: 
                    278: /*
                    279:  * Macro for transmission of data.
                    280:  *
                    281:  * cp->lock must be held throughout.
                    282:  */
                    283: #define tcp_xmit_data(cp,ctlcode,a_trid,a_code,a_kmsg,a_len,a_crypt,ret) {     \
                    284:        int             b_len;                                          \
                    285:                                                                        \
                    286:        if (a_kmsg) {                                                   \
                    287:                (a_kmsg)->tcp_ctl.ctl = htonl(ctlcode);                 \
                    288:                (a_kmsg)->tcp_ctl.trid = htonl(a_trid);                 \
                    289:                (a_kmsg)->tcp_ctl.code = htonl(a_code);                 \
                    290:                (a_kmsg)->tcp_ctl.size = htonl(a_len);                  \
                    291:                (a_kmsg)->tcp_ctl.crypt_level = htonl(a_crypt);         \
                    292:                                                                        \
                    293:                DEBUG6(TCP_DBG_VERBOSE,0,2800,cp,ctlcode,a_trid,        \
                    294:                                        a_code,&a_kmsg,a_crypt);        \
                    295:                                                                        \
                    296:                /*                                                      \
                    297:                 * XXX Worry about data encryption.                     \
                    298:                 */                                                     \
                    299:                                                                        \
                    300:                /*                                                      \
                    301:                 * Send everything in one pass.                         \
                    302:                 */                                                     \
                    303:                b_len = sizeof(tcp_ctl_t) + (a_len);                    \
                    304:                ret = mach_tcp_send(PORT_NULL,(cp)->sock,               \
                    305:                                        &((a_kmsg)->tcp_ctl),&b_len,0); \
                    306:                INCSTAT(tcp_send);                                      \
                    307:                DEBUG3(TCP_DBG_VERBOSE,0,2801,b_len,ret,errno); \
                    308:        } else {                                                        \
                    309:                tcp_xmit_control((cp),(ctlcode),(a_trid),(a_code),(ret));       \
                    310:        }                                                               \
                    311: }
                    312: 
                    313: 
                    314: 
                    315: /*
                    316:  * np_printf --
                    317:  *
                    318:  * Special version of printf to avoid using sprintf in ERROR.
                    319:  */
                    320: np_printf(msg,fmt,p1,p2,p3,p4,p5,p6)
                    321:        char    *msg;
                    322:        char    *fmt;
                    323:        int     p1;
                    324:        int     p2;
                    325:        int     p3;
                    326:        int     p4;
                    327:        int     p5;
                    328:        int     p6;
                    329: {
                    330:        printf(fmt,p1,p2,p3,p4,p5,p6);
                    331:        printf("\n");
                    332: }
                    333: 
                    334: 
                    335: 
                    336: /*
                    337:  * np_tcp_init_conn --
                    338:  *
                    339:  * Allocate and initialize a new TCP connection record.
                    340:  *
                    341:  * Parameters:
                    342:  *
                    343:  * Results:
                    344:  *
                    345:  * pointer to the new record.
                    346:  *
                    347:  * Side effects:
                    348:  *
                    349:  * Starts a new thread to handle the connection.
                    350:  *
                    351:  * Note:
                    352:  *
                    353:  * conn_lock must be acquired before calling this routine.
                    354:  * It is held throughout its execution.
                    355:  */
                    356: PRIVATE tcp_conn_ptr_t np_tcp_init_conn()
                    357: BEGIN("np_tcp_init_conn")
                    358:        tcp_conn_ptr_t  cp;
                    359:        int             i;
                    360:        char            name[40];
                    361: 
                    362:        /*
                    363:         * Find an unused connection record in the conn_vec array.
                    364:         * We could have used the global memory allocator for that,
                    365:         * but since there are few connection records, why bother...
                    366:         *
                    367:         * conn_lock guarantees mutual exclusion.
                    368:         */
                    369:        cp = NULL;
                    370:        for (i = 0; i < 32; i++) {
                    371:                if (conn_vec[i].state == TCP_INVALID) {
                    372:                        cp = &conn_vec[i];
                    373:                        break;
                    374:                }
                    375:        }
                    376:        if (cp == NULL) {
                    377:                panic("The TCP module cannot allocate a new connection record");
                    378:        }
                    379: 
                    380:        cp->state = TCP_FREE;
                    381:        cp->sock = 0;
                    382:        cp->count = 0;
                    383:        cp->dest = 0;
                    384:        mutex_init(&cp->lock);
                    385:        mutex_lock(&cp->lock);
                    386:        condition_init(&cp->cond);
                    387:        queue_init(&cp->trans);
                    388:        cp->th = NULL;
                    389: #if    NeXT
                    390:        (void) kernel_thread(kernel_task,np_tcp_conn_handler);
                    391: #else  NeX T
                    392:        (void) kernel_thread(first_task,np_tcp_conn_handler);
                    393: #endif NeXT
                    394: /*     sprintf(name,"np_tcp_conn_handler(0x%x)",cp); */
                    395: 
                    396:        DEBUG2(TCP_DBG_MAJOR,0,2805,cp,cp->th);
                    397: 
                    398:        mutex_unlock(&cp->lock);
                    399: 
                    400:        RETURN(cp);
                    401: END
                    402: 
                    403: 
                    404: 
                    405: /*
                    406:  * np_tcp_close_conn --
                    407:  *
                    408:  * Arrange to close down one TCP connection as soon as possible.
                    409:  *
                    410:  * Parameters:
                    411:  *
                    412:  * Results:
                    413:  *
                    414:  * Side effects:
                    415:  *
                    416:  * Note:
                    417:  *
                    418:  * conn_lock must be acquired before calling this routine.
                    419:  * It is held throughout its execution.
                    420:  */
                    421: PRIVATE void np_tcp_close_conn()
                    422: BEGIN("np_tcp_close_conn")
                    423:        tcp_conn_ptr_t          first;
                    424:        tcp_conn_ptr_t          cp;
                    425:        kern_return_t           ret;
                    426: 
                    427:        /*
                    428:         * Look for an old connection to recycle.
                    429:         */
                    430:        first = (tcp_conn_ptr_t)queue_first(&conn_lru);
                    431:        cp = (tcp_conn_ptr_t)queue_last(&conn_lru);
                    432:        while (cp != first) {
                    433:                if (cp->count == 0) {
                    434:                        mutex_lock(&cp->lock);
                    435:                        if ((cp->count == 0) && (cp->state == TCP_CONNECTED)) {
                    436:                                break;
                    437:                        } else {
                    438:                                mutex_unlock(&cp->lock);
                    439:                        }
                    440:                }
                    441:                cp = (tcp_conn_ptr_t)queue_prev(&cp->connq);
                    442:        }
                    443:        if (cp == first) {
                    444:                /*
                    445:                 * We are over-committed. We will try again
                    446:                 * to close something at the next request or
                    447:                 * reply.
                    448:                 *
                    449:                 * XXX We could also set a timer to kill someone at
                    450:                 * random, to give new clients a chance.
                    451:                 */
                    452:                DEBUG2(TCP_DBG_MAJOR,0,2838,conn_num,conn_closing);
                    453:        } else {
                    454:                /*
                    455:                 * Close this unused connection.
                    456:                 */
                    457:                DEBUG4(TCP_DBG_MAJOR,0,2839,cp,cp->dest,conn_num,conn_closing);
                    458:                cp->state = TCP_CLOSING;
                    459:                conn_closing++;
                    460:                tcp_xmit_control(cp,TCP_CTL_CLOSEREQ,0,0,ret);
                    461:                mutex_unlock(&cp->lock);
                    462:        }
                    463: 
                    464:        RET;
                    465: END
                    466: 
                    467: 
                    468: 
                    469: /*
                    470:  * netport_tcp_sendrequest --
                    471:  *
                    472:  * Send a request through the TCP interface.
                    473:  *
                    474:  * Parameters:
                    475:  *
                    476:  *     client_id       : an identifier assigned by the client to this transaction
                    477:  *     kmsg            : the data to be sent
                    478:  *     len             : the length of the data in kmsg
                    479:  *     to              : the destination of the request
                    480:  *     crypt_level     : whether the data should be encrypted
                    481:  *
                    482:  * Results:
                    483:  *
                    484:  *     TR_SUCCESS or a specific failure code.
                    485:  *
                    486:  * Side effects:
                    487:  *
                    488:  * Design:
                    489:  *
                    490:  * Note:
                    491:  *
                    492:  */
                    493: EXPORT int netport_tcp_sendrequest(client_id,kmsg,len,to,crypt_level)
                    494: int            client_id;
                    495: kern_msg_t     kmsg;
                    496: int            len;
                    497: netaddr_t      to;
                    498: int            crypt_level;
                    499: BEGIN("netport_tcp_sendrequest")
                    500:        tcp_conn_ptr_t          first;
                    501:        tcp_conn_ptr_t          cp;
                    502:        tcp_trans_ptr_t         tp;
                    503:        kern_return_t           ret;
                    504: 
                    505:        mutex_lock(&conn_lock);
                    506:        DEBUG4(TCP_DBG_VERBOSE,0,2837,to,client_id,conn_num,conn_closing);
                    507:        INCSTAT(tcp_requests_sent);
                    508: 
                    509:        /*
                    510:         * Find an open connection to the destination.
                    511:         */
                    512:        first = (tcp_conn_ptr_t)queue_first(&conn_lru);
                    513:        cp = first;
                    514:        while (!queue_end(&conn_lru,(queue_entry_t)cp)) {
                    515:                if (cp->dest == to) {
                    516:                        break;
                    517:                }
                    518:                cp = (tcp_conn_ptr_t)queue_next(&cp->connq);
                    519:        }
                    520: 
                    521:        if (queue_end(&conn_lru,(queue_entry_t)cp)) {
                    522:                /*
                    523:                 * Could not find an open connection.
                    524:                 */
                    525:                if (conn_num < TCP_CONN_OPENING) {
                    526:                        /*
                    527:                         * Immediately start a new connection.
                    528:                         */
                    529:                        if (queue_empty(&conn_free)) {
                    530:                                /*
                    531:                                 * Initialize a new connection record.
                    532:                                 */
                    533:                                cp = np_tcp_init_conn();
                    534:                        } else {
                    535:                                cp = (tcp_conn_ptr_t)queue_first(&conn_free);
                    536:                                queue_remove(&conn_free,cp,
                    537:                                                        tcp_conn_ptr_t,connq);
                    538:                        }
                    539:                        mutex_lock(&cp->lock);
                    540:                        DEBUG2(TCP_DBG_MAJOR,0,2840,cp,to);
                    541:                        queue_enter_first(&conn_lru,cp,tcp_conn_ptr_t,connq);
                    542:                        conn_num++;
                    543:                        cp->dest = to;
                    544:                        cp->state = TCP_OPENING;
                    545:                        cp->count = 1;
                    546: #ifdef notdef
                    547:                        /*
                    548:                         * This is done when placing cp on the free list.
                    549:                         */
                    550:                        queue_init(&cp->trans);
                    551: #endif notdef
                    552:                        condition_signal(&cp->cond);
                    553:                        mutex_unlock(&cp->lock);
                    554:                        if ((conn_num - conn_closing) > TCP_CONN_STEADY) {
                    555:                                np_tcp_close_conn();
                    556:                        }
                    557:                        mutex_unlock(&conn_lock);
                    558:                } else {
                    559:                        /*
                    560:                         * We are over-committed. Tell the caller to wait.
                    561:                         */
                    562:                        DEBUG0(TCP_DBG_MAJOR,0,2841);
                    563:                        if ((conn_num - conn_closing) > TCP_CONN_STEADY) {
                    564:                                np_tcp_close_conn();
                    565:                        }
                    566:                        mutex_unlock(&conn_lock);
                    567:                        RETURN(TR_OVERLOAD);
                    568:                }
                    569:        } else {
                    570:                /*
                    571:                 * Found an open connection. Use it!
                    572:                 */
                    573:                DEBUG2(TCP_DBG_VERBOSE,0,2842,cp,cp->dest);
                    574:                if (cp != first) {
                    575:                        /*
                    576:                         * Place the record at the head of the queue.
                    577:                         */
                    578:                        queue_remove(&conn_lru,cp,tcp_conn_ptr_t,connq);
                    579:                        queue_enter_first(&conn_lru,cp,tcp_conn_ptr_t,connq);
                    580:                }
                    581:                if ((conn_num - conn_closing) > TCP_CONN_STEADY) {
                    582:                        np_tcp_close_conn();
                    583:                }
                    584:                mutex_lock(&cp->lock);
                    585:                cp->count++;
                    586:                mutex_unlock(&conn_lock);
                    587:        }
                    588: 
                    589:        /*
                    590:         * At this point, we have a lock on a connection record for the
                    591:         * right destination. See if we can transmit the data.
                    592:         */
                    593: 
                    594:        /*
                    595:         * Link the transaction record in the connection record.
                    596:         */
                    597:        ZALLOC(tcp_trans_zone,tp,tcp_trans_ptr_t);
                    598:        if (tp == NULL) {
                    599:                panic("netport_tcp_sendrequest: cannot get a transaction record");
                    600:        }
                    601:        tp->client_id = client_id;
                    602:        TRID_SET_CLIENT(tp->trid);
                    603: 
                    604:        DEBUG4(TCP_DBG_VERBOSE,0,2843,cp,cp->state,tp,tp->trid);
                    605: 
                    606:        if (cp->state == TCP_FREE) {
                    607:                panic("TCP module trying to transmit on a free connection");
                    608:        }
                    609: 
                    610:        if (cp->state == TCP_CONNECTED) {
                    611:                /*
                    612:                 * Send all the data on the socket.
                    613:                 */
                    614:                tp->state = TCP_TR_PENDING;
                    615:                tcp_xmit_data(cp,TCP_CTL_REQUEST,tp->trid,0,kmsg,len,crypt_level,ret);
                    616:                if (ret != KERN_SUCCESS) {
                    617:                        /*
                    618:                         * Something went wrong. Most probably, the client is dead.
                    619:                         */
                    620:                        DEBUG2(TCP_DBG_CRASH,0,2844,cp->dest,errno);
                    621:                        cp->count--;
                    622:                        mutex_unlock(&cp->lock);
                    623:                        ZFREE(tcp_trans_zone,tp);
                    624:                        RETURN(TR_FAILURE);
                    625:                }
                    626:        } else {
                    627:                tp->state = TCP_TR_WAITING;
                    628:                tp->kmsg = kmsg;
                    629:                tp->len = len;
                    630:                tp->crypt_level = crypt_level;
                    631:        }
                    632:        queue_enter(&cp->trans,tp,tcp_trans_ptr_t,transq);
                    633:        mutex_unlock(&cp->lock);
                    634: 
                    635:        RETURN(TR_SUCCESS);
                    636: END
                    637: 
                    638: 
                    639: 
                    640: /*
                    641:  * netport_tcp_sendreply --
                    642:  *
                    643:  * Send a response through the TCP interface.
                    644:  *
                    645:  * Parameters:
                    646:  *
                    647:  *     trid            : transport-level ID for a previous operation on this
                    648:  *                       transaction
                    649:  *     code            : a return code to be passed to the client.
                    650:  *     kmsg            : the data to be sent
                    651:  *     len             : the length of the data in kmsg
                    652:  *     crypt_level     : whether the data should be encrypted
                    653:  *
                    654:  * Results:
                    655:  *
                    656:  *     TR_SUCCESS or a specific failure code.
                    657:  *
                    658:  * Side effects:
                    659:  *
                    660:  * Design:
                    661:  *
                    662:  * Note:
                    663:  *
                    664:  */
                    665: EXPORT int netport_tcp_sendreply(trid,code,kmsg,len,crypt_level)
                    666: trid_t         trid;
                    667: int            code;
                    668: kern_msg_t     kmsg;
                    669: int            len;
                    670: int            crypt_level;
                    671: BEGIN("netport_tcp_sendreply")
                    672:        tcp_conn_ptr_t  cp;
                    673:        kern_return_t   ret;
                    674:        int             tcpid;
                    675: 
                    676:        SET_TCPID(tcpid,trid);
                    677:        TRID_GET_SERVER(tcpid,cp);
                    678: 
                    679:        /*
                    680:         * If the client has died, the connection record may
                    681:         * already have been reused, and we may be sending this reply
                    682:         * to the wrong machine. This should be detected by the 
                    683:         * incarnation number in the trid.
                    684:         */
                    685:        if (cp == NULL) {
                    686:                DEBUG1(TCP_DBG_CRASH,0,2847,tcpid);
                    687:                RETURN(TR_FAILURE);
                    688:        }
                    689: 
                    690:        mutex_lock(&cp->lock);
                    691: 
                    692:        DEBUG4(TCP_DBG_VERBOSE,0,2845,tcpid,cp,cp->dest,cp->state);
                    693:        INCSTAT(tcp_replies_sent);
                    694: 
                    695:        if (cp->state != TCP_CONNECTED) {
                    696:                /*
                    697:                 * The client has died or the connection has just
                    698:                 * been dropped. Drop the reply.
                    699:                 */
                    700:                mutex_unlock(&cp->lock);
                    701:                RETURN(TR_FAILURE);
                    702:        }
                    703: 
                    704:        cp->count--;
                    705:        tcp_xmit_data(cp,TCP_CTL_REPLY,tcpid,code,kmsg,len,crypt_level,ret);
                    706: 
                    707:        if (ret != KERN_SUCCESS) {
                    708:                /*
                    709:                 * Something went wrong. Most probably, the client is dead.
                    710:                 */
                    711:                DEBUG2(TCP_DBG_CRASH,0,2846,cp->dest,errno);
                    712:                mutex_unlock(&cp->lock);
                    713:                RETURN(TR_FAILURE);
                    714:        }
                    715: 
                    716:        mutex_unlock(&cp->lock);
                    717: 
                    718:        /*
                    719:         * Update the LRU list of active connections and check for
                    720:         * excess connections.
                    721:         */
                    722:        mutex_lock(&conn_lock);
                    723:        if (cp != (tcp_conn_ptr_t)queue_first(&conn_lru)) {
                    724:                /*
                    725:                 * Place the record at the head of the queue.
                    726:                 */
                    727:                queue_remove(&conn_lru,cp,tcp_conn_ptr_t,connq);
                    728:                queue_enter_first(&conn_lru,cp,tcp_conn_ptr_t,connq);
                    729:        }
                    730:        if ((conn_num - conn_closing) > TCP_CONN_STEADY) {
                    731:                np_tcp_close_conn();
                    732:        }
                    733:        mutex_unlock(&conn_lock);
                    734: 
                    735:        RETURN(TR_SUCCESS);
                    736: END
                    737: 
                    738: 
                    739: 
                    740: /*
                    741:  * np_tcp_conn_handler_open --
                    742:  *
                    743:  * Handler for one connection - opening phase.
                    744:  *
                    745:  * Parameters:
                    746:  *
                    747:  * cp: pointer to the connection record.
                    748:  *
                    749:  * Results:
                    750:  *
                    751:  * TRUE if the connection was successfully opened, FALSE otherwise.
                    752:  *
                    753:  * Side effects:
                    754:  *
                    755:  * Transactions waiting in the connection record are initiated.
                    756:  *
                    757:  * Note:
                    758:  *
                    759:  * cp->lock must be locked on entry. It is also locked on exit, but
                    760:  * it may be unlocked during the execution of this procedure.
                    761:  */
                    762: PRIVATE boolean_t np_tcp_conn_handler_open(cp)
                    763:        tcp_conn_ptr_t  cp;
                    764: BEGIN("np_tcp_conn_handler_open")
                    765:        tcp_trans_ptr_t         tp;
                    766:        struct socket           *cs;
                    767:        struct sockaddr_in      sname;
                    768: /*     netaddr_t               peeraddr; */
                    769:        kern_return_t           ret;
                    770: 
                    771:        sname.sin_family = AF_INET;
                    772:        sname.sin_port = htons(TCP_NETMSG_PORT);
                    773:        sname.sin_addr.s_addr = (u_long)(cp->dest);
                    774: /*     peeraddr = cp->dest; */
                    775: 
                    776:        /*
                    777:         * Unlock the record while we are waiting for the connection
                    778:         * to be established.
                    779:         */
                    780:        mutex_unlock(&cp->lock);
                    781: 
                    782:        mutex_lock(&conn_lock);
                    783:        ret = mach_tcp_socket(PORT_NULL,&cs);
                    784:        mutex_unlock(&conn_lock);
                    785:        if (ret != KERN_SUCCESS) {
                    786:                ERROR((msg,"np_tcp_conn_handler.socket failed: errno=%d",errno));
                    787:                panic("tcp");
                    788:        }
                    789: 
                    790:        if (np_flags & NP_SODEBUG) {
                    791:                cs->so_options |= SO_DEBUG;
                    792:        }
                    793: 
                    794:        ret = mach_tcp_connect(PORT_NULL,cs,&sname,sizeof(struct sockaddr_in));
                    795:        if (ret != KERN_SUCCESS) {
                    796:                DEBUG2(TCP_DBG_CRASH,0,2815,0,errno);
                    797:                mutex_lock(&cp->lock);
                    798:                RETURN(FALSE);
                    799:        }
                    800:        INCSTAT(tcp_connect);
                    801: 
                    802:        mutex_lock(&cp->lock);
                    803:        cp->sock = cs;
                    804:        cp->state = TCP_CONNECTED;
                    805:        DEBUG3(TCP_DBG_VERBOSE,0,2816,cp,cs,0);
                    806: 
                    807:        /*
                    808:         * Look for transactions waiting to be transmitted.
                    809:         */
                    810:        tp = (tcp_trans_ptr_t)queue_first(&cp->trans);
                    811:        while (!queue_end(&cp->trans,(queue_entry_t)tp)) {
                    812:                DEBUG2(TCP_DBG_VERBOSE,0,2817,tp,tp->state);
                    813:                if (tp->state == TCP_TR_WAITING) {
                    814:                        tp->state = TCP_TR_PENDING;
                    815:                        tcp_xmit_data(cp,TCP_CTL_REQUEST,tp->trid,0,
                    816:                                        tp->kmsg,tp->len,tp->crypt_level,ret);
                    817:                        if (ret != KERN_SUCCESS) {
                    818:                                RETURN(FALSE);
                    819:                        }
                    820:                }
                    821:                tp = (tcp_trans_ptr_t)queue_next(&tp->transq);
                    822:        }
                    823: 
                    824:        RETURN(TRUE);
                    825: END
                    826: 
                    827: 
                    828: 
                    829: /*
                    830:  * np_tcp_conn_handler_active --
                    831:  *
                    832:  * Handler for one connection - active phase.
                    833:  *
                    834:  * Parameters:
                    835:  *
                    836:  * cp: pointer to the connection record.
                    837:  *
                    838:  * Results:
                    839:  *
                    840:  * Exits when the connection should be closed.
                    841:  *
                    842:  * Note:
                    843:  *
                    844:  * For now, the data received on the connection is only kept until the
                    845:  * higher-level handler procedure (disp_in_request or reply_proc) returns.
                    846:  * This allows the use of a data buffer on the stack.
                    847:  *
                    848:  */
                    849: PRIVATE void np_tcp_conn_handler_active(cp)
                    850:        tcp_conn_ptr_t  cp;
                    851: BEGIN("np_tcp_conn_handler_active")
                    852:        struct socket           *cs;
                    853:        netaddr_t               peeraddr;
                    854:        tcp_trans_ptr_t         tp;
                    855:        kern_return_t           ret;
                    856:        kern_msg_t              kmsg;
                    857:        kern_msg_t              new_kmsg;
                    858:        int                     len;
                    859:        caddr_t                 bufp;           /* current location in data */
                    860:        int                     buf_count;      /* data available in buf */
                    861:        int                     buf_free;       /* free space in buf */
                    862:        int                     data_size;
                    863:        unsigned long           trid;
                    864:        trid_t                  trid_cl;
                    865:        int                     s;
                    866: 
                    867:        peeraddr = cp->dest;    /* OK not to lock at this point */
                    868:        cs = cp->sock;
                    869:        new_kmsg = NULL;
                    870: 
                    871:        /*
                    872:         * Enter the recv loop.
                    873:         */
                    874:        for (;;) {
                    875: 
                    876:                /*
                    877:                 * Get a fresh kmsg for a receive buffer.
                    878:                 */
                    879:                if (new_kmsg == NULL) {
                    880:                        ZALLOC(netport_kmsg_zone,kmsg,kern_msg_t);
                    881:                        if (kmsg == NULL) {
                    882:                                panic("netport out of kmsgs");
                    883:                        }
                    884:                        kmsg->home_zone = netport_kmsg_zone;
                    885:                        bufp = (caddr_t)&(kmsg->tcp_ctl);
                    886:                        buf_count = 0;
                    887:                        buf_free = DATA_SIZE_MAX;
                    888:                } else {
                    889:                        /*
                    890:                         * There is already some data obtained
                    891:                         * in the previous pass.
                    892:                         */
                    893:                        kmsg = new_kmsg;
                    894:                }
                    895:                
                    896:                /*
                    897:                 * Get at least a tcp control header in the
                    898:                 * buffer.
                    899:                 */
                    900:                while (buf_count < sizeof(tcp_ctl_t)) {
                    901:                        len = buf_free;
                    902:                        ret = mach_tcp_recv(PORT_NULL,cs,bufp,&len,0);
                    903:                        if ((ret != KERN_SUCCESS) || (len <= 0)) {
                    904:                                ZFREE(netport_kmsg_zone,kmsg);
                    905:                                RET;
                    906:                        }
                    907:                        INCSTAT(tcp_recv);
                    908:                        DEBUG2(TCP_DBG_VERBOSE,0,2820,ret,peeraddr);
                    909:                        buf_count += len;
                    910:                        buf_free -= len;
                    911:                        bufp += len;
                    912:                }
                    913: 
                    914:                /*
                    915:                 * Do all the required byte-swapping (Sigh!).
                    916:                 */
                    917:                kmsg->tcp_ctl.ctl               = ntohl(kmsg->tcp_ctl.ctl);
                    918:                kmsg->tcp_ctl.trid              = ntohl(kmsg->tcp_ctl.trid);
                    919:                kmsg->tcp_ctl.code              = ntohl(kmsg->tcp_ctl.code);
                    920:                kmsg->tcp_ctl.size              = ntohl(kmsg->tcp_ctl.size);
                    921:                kmsg->tcp_ctl.crypt_level       = ntohl(kmsg->tcp_ctl.crypt_level);
                    922: 
                    923:                /*
                    924:                 * Read any user data.
                    925:                 * Advance the current data pointer.
                    926:                 */
                    927:                buf_count -= sizeof(tcp_ctl_t);
                    928:                data_size = kmsg->tcp_ctl.size;
                    929:                if (data_size > (buf_count + buf_free)) {
                    930:                        ERROR((msg,"Netport: size too big from 0x%x\n", peeraddr));
                    931:                        ZFREE(netport_kmsg_zone,kmsg);
                    932:                        RET;
                    933:                }
                    934:                while (buf_count < data_size) {
                    935:                        len = buf_free;
                    936:                        ret = mach_tcp_recv(PORT_NULL,cs,bufp,&len,0);
                    937:                        if ((ret != KERN_SUCCESS) || (len <= 0)) {
                    938:                                ZFREE(netport_kmsg_zone,kmsg);
                    939:                                RET;
                    940:                        }
                    941:                        INCSTAT(tcp_recv);
                    942:                        buf_count += len;
                    943:                        buf_free -= len;
                    944:                        bufp += len;
                    945:                }
                    946: 
                    947:                /*
                    948:                 * If we received more data than we asked for,
                    949:                 * transfer the excess in a new kmsg.
                    950:                 */
                    951:                if (buf_count > data_size) {
                    952:                        ZALLOC(netport_kmsg_zone,new_kmsg,kern_msg_t);
                    953:                        if (new_kmsg == NULL) {
                    954:                                panic("netport out of kmsgs");
                    955:                        }
                    956:                        new_kmsg->home_zone = netport_kmsg_zone;
                    957:                        bcopy(((caddr_t)&(kmsg->netmsg_hdr)) + data_size,
                    958:                                                (caddr_t)&(new_kmsg->tcp_ctl), 
                    959:                                                buf_count - data_size);
                    960:                        buf_count -= data_size;
                    961:                        bufp = (caddr_t)(&(new_kmsg->tcp_ctl)) + buf_count;
                    962:                        buf_free = DATA_SIZE_MAX - buf_count;
                    963:                } else {
                    964:                        new_kmsg = NULL;
                    965:                }
                    966: 
                    967:                /*
                    968:                 * XXX Worry about encryption.
                    969:                 */
                    970: 
                    971:                /*
                    972:                 * Now process the message.
                    973:                 */
                    974:                DEBUG1(TCP_DBG_VERBOSE,0,2826,kmsg->tcp_ctl.ctl);
                    975:                switch(kmsg->tcp_ctl.ctl) {
                    976:                        case TCP_CTL_REQUEST:
                    977:                                INCSTAT(tcp_requests_rcvd);
                    978:                                mutex_lock(&cp->lock);
                    979:                                cp->count++;
                    980:                                if (cp->state == TCP_CLOSING) {
                    981:                                        cp->state = TCP_CONNECTED;
                    982:                                        mutex_unlock(&cp->lock);
                    983:                                        mutex_lock(&conn_lock);
                    984:                                        conn_closing--;
                    985:                                        mutex_unlock(&conn_lock);
                    986:                                } else {
                    987:                                        mutex_unlock(&cp->lock);
                    988:                                }
                    989:                                trid = kmsg->tcp_ctl.trid;
                    990:                                TRID_SET_SERVER(trid,cp);
                    991:                                SET_TRID(trid_cl,trid);
                    992:                                (void) netport_handle_rq(TR_TCP_ENTRY,trid_cl,
                    993:                                                kmsg,data_size,peeraddr,
                    994:                                                kmsg->tcp_ctl.crypt_level,FALSE);
                    995:                                /*
                    996:                                 * The kmsg will be destroyed by netmsg_input_rq.
                    997:                                 */
                    998: #ifdef notdef
                    999:                                if (disp_ret != DISP_WILL_REPLY) {
                   1000:                                        mutex_lock(&cp->lock);
                   1001:                                        DEBUG3(TCP_DBG_VERBOSE,0,2827,peeraddr,
                   1002:                                                                trid,disp_ret);
                   1003:                                        tcp_xmit_control(cp,TCP_CTL_REPLY,trid,
                   1004:                                                                disp_ret,ret);
                   1005:                                        cp->count--;
                   1006:                                        mutex_unlock(&cp->lock);
                   1007:                                        if (ret != KERN_SUCCESS) {
                   1008:                                                RET;
                   1009:                                        }
                   1010:                                }
                   1011: #endif notdef
                   1012:                                break;
                   1013: 
                   1014:                        case TCP_CTL_REPLY:
                   1015:                                INCSTAT(tcp_replies_rcvd);
                   1016:                                mutex_lock(&cp->lock);
                   1017:                                if (cp->state == TCP_CLOSING) {
                   1018:                                        cp->state = TCP_CONNECTED;
                   1019:                                        mutex_unlock(&cp->lock);
                   1020:                                        mutex_lock(&conn_lock);
                   1021:                                        conn_closing--;
                   1022:                                        mutex_unlock(&conn_lock);
                   1023:                                        mutex_lock(&cp->lock);
                   1024:                                }
                   1025:                                /*
                   1026:                                 * Find the transaction record.
                   1027:                                 */
                   1028:                                TRID_GET_CLIENT(kmsg->tcp_ctl.trid,trid);
                   1029:                                tp = (tcp_trans_ptr_t)queue_first(&cp->trans);
                   1030:                                while (!queue_end(&cp->trans,(queue_entry_t)tp)) {
                   1031:                                        if (tp->trid == trid) {
                   1032:                                                break;
                   1033:                                        }
                   1034:                                        tp = (tcp_trans_ptr_t)queue_next(&tp->transq);
                   1035:                                }
                   1036:                                if (queue_end(&cp->trans,(queue_entry_t)tp)) {
                   1037:                                        ERROR((msg,
                   1038: "np_tcp_conn_handler_active: cannot find the transaction record for a reply"));
                   1039:                                        mutex_unlock(&cp->lock);
                   1040:                                        ZFREE(netport_kmsg_zone,kmsg);
                   1041:                                } else {
                   1042:                                        queue_remove(&cp->trans,tp,
                   1043:                                                        tcp_trans_ptr_t,transq);
                   1044:                                        cp->count--;
                   1045:                                        mutex_unlock(&cp->lock);
                   1046:                                        DEBUG1(TCP_DBG_VERBOSE,0,2828,tp);
                   1047:                                        netport_handle_rp(tp->client_id,
                   1048:                                                kmsg->tcp_ctl.code,kmsg,data_size);
                   1049:                                        /*
                   1050:                                         * The kmsg will be destroyed by
                   1051:                                         * the reply_proc.
                   1052:                                         */
                   1053:                                        ZFREE(tcp_trans_zone,tp);
                   1054:                                }
                   1055:                                break;
                   1056: 
                   1057:                        case TCP_CTL_CLOSEREQ:
                   1058:                                mutex_lock(&cp->lock);
                   1059:                                if (cp->count == 0) {
                   1060:                                        /*
                   1061:                                         * Send CLOSEREP.
                   1062:                                         */
                   1063:                                        DEBUG1(TCP_DBG_MAJOR,0,2829,cp->dest);
                   1064:                                        tcp_xmit_control(cp,TCP_CTL_CLOSEREP,
                   1065:                                                                        0,0,ret);
                   1066:                                        if (cp->state != TCP_CLOSING) {
                   1067:                                                cp->state = TCP_CLOSED;
                   1068:                                        }
                   1069:                                        mutex_unlock(&cp->lock);
                   1070:                                        ZFREE(netport_kmsg_zone,kmsg);
                   1071:                                        RET;
                   1072:                                } else {
                   1073:                                        /*
                   1074:                                         * We have some data in
                   1075:                                         * transit. Nothing more
                   1076:                                         * should be needed.
                   1077:                                         */
                   1078:                                        DEBUG2(TCP_DBG_MAJOR,0,2830,cp->dest,
                   1079:                                                                        cp->count);
                   1080:                                        cp->state = TCP_CONNECTED;
                   1081:                                        mutex_unlock(&cp->lock);
                   1082:                                        ZFREE(netport_kmsg_zone,kmsg);
                   1083:                                }
                   1084:                                break;
                   1085: 
                   1086:                        case TCP_CTL_CLOSEREP:
                   1087:                                mutex_lock(&cp->lock);
                   1088:                                DEBUG1(TCP_DBG_MAJOR,0,2831,cp->dest);
                   1089:                                /*
                   1090:                                 * cp->state can only be TCP_CLOSING:
                   1091:                                 *
                   1092:                                 * We have sent a CLOSEREQ, and set the
                   1093:                                 * state to TCP_CLOSING then. If the state
                   1094:                                 * has changed since then, it must be because
                   1095:                                 * we have received data. But this data can only
                   1096:                                 * be a request, because we had nothing going on
                   1097:                                 * when we sent the CLOSEREQ. This CLOSEREQ must
                   1098:                                 * arrive at the other end before our reply
                   1099:                                 * because TCP does not reorder messages. But
                   1100:                                 * then the CLOSEREQ will be rejected because
                   1101:                                 * of the pending transaction.
                   1102:                                 */
                   1103:                                mutex_unlock(&cp->lock);
                   1104:                                ZFREE(netport_kmsg_zone,kmsg);
                   1105:                                RET;
                   1106: 
                   1107:                        default:
                   1108:                                ERROR((msg,
                   1109:                "np_tcp_conn_handler_active: received an unknown ctl code: %d",
                   1110:                                                                kmsg->tcp_ctl.ctl));
                   1111:                                ZFREE(netport_kmsg_zone,kmsg);
                   1112:                                break;
                   1113:                }
                   1114:        }
                   1115: 
                   1116: END
                   1117: 
                   1118: 
                   1119: 
                   1120: /*
                   1121:  * np_tcp_conn_handler_close --
                   1122:  *
                   1123:  * Handler for one connection - closing phase.
                   1124:  *
                   1125:  * Parameters:
                   1126:  *
                   1127:  * cp: pointer to the connection record.
                   1128:  *
                   1129:  * Results:
                   1130:  *
                   1131:  * none.
                   1132:  *
                   1133:  * Note:
                   1134:  *
                   1135:  */
                   1136: PRIVATE void np_tcp_conn_handler_close(cp)
                   1137:        tcp_conn_ptr_t  cp;
                   1138: BEGIN("np_tcp_conn_handler_close")
                   1139:        tcp_trans_ptr_t         tp;
                   1140:        int                     s;
                   1141: 
                   1142:        /*
                   1143:         * Some transactions might be initiated after the active phase exits
                   1144:         * and before this phase starts. Hopefully, they will be stopped by
                   1145:         * the TCP_CLOSING or TCP_CLOSED states, or the send will fail.
                   1146:         */
                   1147:        mutex_lock(&conn_lock);
                   1148:        mutex_lock(&cp->lock);
                   1149:        mach_tcp_close(PORT_NULL,cp->sock);
                   1150:        INCSTAT(tcp_close);
                   1151:        if (cp->state == TCP_CLOSING) {
                   1152:                conn_closing--;
                   1153:        }
                   1154:        cp->state = TCP_FREE;
                   1155: 
                   1156:        /*
                   1157:         * Go down the list of waiting/pending transactions
                   1158:         * and abort them.
                   1159:         * The client is of course free to retry them later.
                   1160:         */
                   1161:        while (!queue_empty(&cp->trans)) {
                   1162:                tp = (tcp_trans_ptr_t)queue_first(&cp->trans);
                   1163:                DEBUG3(TCP_DBG_VERBOSE,0,2834,tp,tp->state,tp->client_id);
                   1164:                if (tp->state == TCP_TR_WAITING) {
                   1165:                        netport_handle_rp(tp->client_id,TR_SEND_FAILURE,0,0);
                   1166:                } else {
                   1167:                        netport_handle_rp(tp->client_id,TR_FAILURE,0,0);
                   1168:                }
                   1169:                queue_remove(&cp->trans,tp,tcp_trans_ptr_t,transq);
                   1170:                ZFREE(tcp_trans_zone,tp);
                   1171:        }
                   1172:        queue_init(&cp->trans);
                   1173:        cp->count = 0;
                   1174:        queue_remove(&conn_lru,cp,tcp_conn_ptr_t,connq);
                   1175:        queue_enter(&conn_free,cp,tcp_conn_ptr_t,connq);
                   1176:        mutex_unlock(&cp->lock);
                   1177:        conn_num--;
                   1178:        DEBUG1(TCP_DBG_MAJOR,0,2835,conn_num);
                   1179:        if (conn_num == (TCP_CONN_MAX - 1)) {
                   1180:                /*
                   1181:                 * OK to start accepting connections again.
                   1182:                 */
                   1183:                DEBUG0(TCP_DBG_MAJOR,0,2836);
                   1184:                condition_signal(&conn_cond);
                   1185:        }
                   1186:        mutex_unlock(&conn_lock);
                   1187: 
                   1188:        RET;
                   1189: END
                   1190: 
                   1191: 
                   1192: 
                   1193: /*
                   1194:  * np_tcp_conn_handler --
                   1195:  *
                   1196:  * Handler for one connection.
                   1197:  *
                   1198:  * Parameters:
                   1199:  *
                   1200:  * Results:
                   1201:  *
                   1202:  *     Should never exit.
                   1203:  *
                   1204:  * Note:
                   1205:  *
                   1206:  * The first thing the thread must do is locate the connection record which
                   1207:  * it is to service. This is guaranteed to succeed because there are exactly
                   1208:  * as many threads as there are valid connection records.
                   1209:  *
                   1210:  * For clarity, this code is split into three different procedures handling
                   1211:  * the opening, active and closing phases of the life of the connection.
                   1212:  *
                   1213:  */
                   1214: PRIVATE void np_tcp_conn_handler()
                   1215: BEGIN("np_tcp_conn_handler")
                   1216:        tcp_conn_ptr_t  cp;
                   1217:        int             i;
                   1218:        boolean_t       active;
                   1219: 
                   1220:        /*
                   1221:         * Find the connection record.
                   1222:         */
                   1223:        mutex_lock(&conn_lock);
                   1224:        cp = NULL;
                   1225:        for (i = 0; i < 32; i++) {
                   1226:                if (conn_vec[i].state != TCP_INVALID) {
                   1227:                        cp = &conn_vec[i];
                   1228:                        if (cp->th == NULL) {
                   1229:                                cp->th = current_thread();
                   1230:                                break;
                   1231:                        } else {
                   1232:                                cp = NULL;
                   1233:                        }
                   1234:                }
                   1235:        }
                   1236:        mutex_unlock(&conn_lock);
                   1237:        if (cp == NULL) {
                   1238:                panic("TCP connection handler cannot find a connection record");
                   1239:        }
                   1240: 
                   1241:        /*
                   1242:         * Service loop.
                   1243:         */
                   1244:        for (;;) {
                   1245:                /*
                   1246:                 * First wait to be activated.
                   1247:                 */
                   1248:                mutex_lock(&cp->lock);
                   1249:                while(cp->state == TCP_FREE) {
                   1250:                        DEBUG0(TCP_DBG_VERBOSE,0,2811);
                   1251:                        condition_wait(&cp->cond,&cp->lock);
                   1252:                }
                   1253: 
                   1254:                /*
                   1255:                 * At this point, the state is either TCP_OPENING (local open)
                   1256:                 * or TCP_CONNECTED (remote open).
                   1257:                 */
                   1258:                DEBUG3(TCP_DBG_VERBOSE,0,2812,cp,cp->state,cp->dest);
                   1259: 
                   1260:                if (cp->state == TCP_OPENING) {
                   1261:                        /*
                   1262:                         * Open a new connection.
                   1263:                         */
                   1264:                        active = np_tcp_conn_handler_open(cp);
                   1265:                } else {
                   1266:                        active = TRUE;
                   1267:                }
                   1268:                cp->incarn = (cp->incarn++) & 0xff;
                   1269:                mutex_unlock(&cp->lock);
                   1270: 
                   1271:                if (active) {
                   1272:                        DEBUG3(TCP_DBG_MAJOR,0,2813,cp,cp->sock,cp->dest);
                   1273:                        np_tcp_conn_handler_active(cp);
                   1274:                        DEBUG3(TCP_DBG_MAJOR,0,2814,cp,cp->sock,cp->dest);
                   1275:                }
                   1276: 
                   1277:                /*
                   1278:                 * Close the connection.
                   1279:                 */
                   1280:                np_tcp_conn_handler_close(cp);
                   1281:        }
                   1282: END
                   1283: 
                   1284: 
                   1285: 
                   1286: /*
                   1287:  * np_tcp_listener --
                   1288:  *
                   1289:  * Handler for the listener socket.
                   1290:  *
                   1291:  * Parameters:
                   1292:  *
                   1293:  * Results:
                   1294:  *
                   1295:  *     Should never exit.
                   1296:  *
                   1297:  * Note:
                   1298:  *
                   1299:  */
                   1300: PRIVATE void np_tcp_listener()
                   1301: BEGIN("np_tcp_listener")
                   1302:        struct socket           *s;
                   1303:        struct socket           *newsock;
                   1304:        kern_return_t           ret;
                   1305:        struct sockaddr_in      sname;
                   1306:        int                     snamelen;
                   1307:        tcp_conn_ptr_t          cp;
                   1308: 
                   1309:        /*
                   1310:         * First create the listener socket.
                   1311:         */
                   1312:        mutex_lock(&conn_lock);
                   1313:        ret = mach_tcp_socket(PORT_NULL,&s);
                   1314:        mutex_unlock(&conn_lock);
                   1315:        if (ret != KERN_SUCCESS) {
                   1316:                ERROR((msg,"np_tcp_listener.socket failed: errno=%d",errno));
                   1317:                panic("tcp");
                   1318:        }
                   1319:        sname.sin_family = AF_INET;
                   1320:        sname.sin_port = htons(TCP_NETMSG_PORT);
                   1321:        sname.sin_addr.s_addr = INADDR_ANY;
                   1322:        ret = mach_tcp_bind(PORT_NULL,s,&sname,sizeof(struct sockaddr_in));
                   1323:        if (ret != KERN_SUCCESS) {
                   1324:                ERROR((msg,"np_tcp_listener.bind failed: errno=%d",errno));
                   1325:                panic("tcp");
                   1326:        }
                   1327:        ret = mach_tcp_listen(PORT_NULL,s,2);
                   1328:        if (ret != KERN_SUCCESS) {
                   1329:                ERROR((msg,"np_tcp_listener.listen failed: errno=%d",errno));
                   1330:                panic("tcp");
                   1331:        }
                   1332:        DEBUG1(TCP_DBG_VERBOSE,0,2806,s);
                   1333: 
                   1334:        /*
                   1335:         * Loop forever accepting connections.
                   1336:         */
                   1337:        for (;;) {
                   1338:                mutex_lock(&conn_lock);
                   1339:                while (conn_num >= TCP_CONN_MAX) {
                   1340:                        DEBUG1(TCP_DBG_VERBOSE,0,2810,conn_num);
                   1341:                        condition_wait(&conn_cond,&conn_lock);
                   1342:                }
                   1343: 
                   1344:                mutex_unlock(&conn_lock);
                   1345:                DEBUG0(TCP_DBG_VERBOSE,0,2807);
                   1346:                snamelen = sizeof(struct sockaddr_in);
                   1347:                ret = mach_tcp_accept(PORT_NULL,s,&sname,&snamelen,&newsock);
                   1348:                if (ret != KERN_SUCCESS) {
                   1349:                        ERROR((msg,
                   1350:                                "np_tcp_listener.accept failed: errno=%d",errno));
                   1351:                        continue;
                   1352:                }
                   1353:                INCSTAT(tcp_accept);
                   1354:                DEBUG0(TCP_DBG_VERBOSE,0,2808);
                   1355: 
                   1356:                if (np_flags & NP_SODEBUG) {
                   1357:                        newsock->so_options |= SO_DEBUG;
                   1358:                }
                   1359: 
                   1360:                mutex_lock(&conn_lock);
                   1361:                if (queue_empty(&conn_free)) {
                   1362:                        /*
                   1363:                         * Initialize a new connection record.
                   1364:                         */
                   1365:                        cp = np_tcp_init_conn();
                   1366:                } else {
                   1367:                        cp = (tcp_conn_ptr_t)queue_first(&conn_free);
                   1368:                        queue_remove(&conn_free,cp,tcp_conn_ptr_t,connq);
                   1369:                }
                   1370:                mutex_lock(&cp->lock);
                   1371:                DEBUG4(TCP_DBG_MAJOR,0,2809,ret,cp,
                   1372:                                        sname.sin_addr.s_addr,sname.sin_port);
                   1373:                queue_enter_first(&conn_lru,cp,tcp_conn_ptr_t,connq);
                   1374:                conn_num++;
                   1375:                cp->sock = newsock;
                   1376:                cp->dest = (netaddr_t)(sname.sin_addr.s_addr);
                   1377:                cp->state = TCP_CONNECTED;
                   1378:                cp->count = 0;
                   1379: #ifdef notdef
                   1380:                /*
                   1381:                 * This is done when placing cp on the free list.
                   1382:                 */
                   1383:                queue_init(&cp->trans);
                   1384: #endif notdef
                   1385:                condition_signal(&cp->cond);
                   1386:                mutex_unlock(&cp->lock);
                   1387:                if ((conn_num - conn_closing) > TCP_CONN_STEADY) {
                   1388:                        np_tcp_close_conn();
                   1389:                }
                   1390:                mutex_unlock(&conn_lock);
                   1391:        }
                   1392: 
                   1393: END
                   1394: 
                   1395: 
                   1396: 
                   1397: /*
                   1398:  * netport_tcp_init --
                   1399:  *
                   1400:  * Initialises the TCP transport protocol.
                   1401:  *
                   1402:  * Parameters:
                   1403:  *
                   1404:  * Results:
                   1405:  *
                   1406:  *     FALSE : we failed to initialise the TCP transport protocol.
                   1407:  *     TRUE  : we were successful.
                   1408:  *
                   1409:  * Side effects:
                   1410:  *
                   1411:  *     Initialises the TCP protocol entry point in the switch array.
                   1412:  *     Allocates the listener port and creates a thread to listen to the network.
                   1413:  *
                   1414:  */
                   1415: EXPORT boolean_t netport_tcp_init()
                   1416: BEGIN("netport_tcp_init")
                   1417:        int             i;
                   1418:        tcp_conn_ptr_t  cp;
                   1419: 
                   1420:        /*
                   1421:         * Initialize the set of connection records and the lists.
                   1422:         */
                   1423:        for (i = 0; i < 32; i++) {
                   1424:                conn_vec[i].state = TCP_INVALID;
                   1425:                conn_vec[i].incarn = 0;
                   1426:        }
                   1427:        mutex_init(&conn_lock);
                   1428:        mutex_lock(&conn_lock);
                   1429:        condition_init(&conn_cond);
                   1430:        queue_init(&conn_lru);
                   1431:        queue_init(&conn_free);
                   1432:        conn_num = 0;
                   1433:        conn_closing = 0;
                   1434:        trid_counter = 10;
                   1435: 
                   1436:        /*
                   1437:         * Create a first connection record (just a test).
                   1438:         */
                   1439:        cp = np_tcp_init_conn();
                   1440:        queue_enter(&conn_free,cp,tcp_conn_ptr_t,connq);
                   1441: 
                   1442:        /*
                   1443:         * Set up the entry in the transport switch.
                   1444:         */
                   1445:        transport_switch[TR_TCP_ENTRY].sendrequest = netport_tcp_sendrequest;
                   1446:        transport_switch[TR_TCP_ENTRY].sendreply = netport_tcp_sendreply;
                   1447: 
                   1448:        /*
                   1449:         * Initialize the zone for transaction records.
                   1450:         */
                   1451:        tcp_trans_zone = zinit(sizeof(tcp_trans_t), 64 * 1024, page_size, FALSE, 
                   1452:                                            "netport TCP transaction records");
                   1453: 
                   1454:        /*
                   1455:         * Initialize the TCP interface.
                   1456:         */
                   1457:        mach_tcp_init(PORT_NULL,NULL);
                   1458: 
                   1459:        /*
                   1460:         * Start the listener.
                   1461:         */
                   1462: #if    NeXT
                   1463:        (void) kernel_thread(kernel_task,np_tcp_listener);
                   1464: #else  NeX T
                   1465:        (void) kernel_thread(first_task,np_tcp_listener);
                   1466: #endif NeXT
                   1467: 
                   1468:        /*
                   1469:         * Get the show on the road...
                   1470:         */
                   1471:        DEBUG0(TCP_DBG_MAJOR,0,2804);
                   1472:        mutex_unlock(&conn_lock);
                   1473:        RETURN(TRUE);
                   1474: 
                   1475: END
                   1476: 
                   1477: 
                   1478: 
                   1479: 
                   1480: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.