Whamcloud - gitweb
invoking section 3 of the GNU LGPL, to instead apply the terms of the GPL
[fs/lustre-release.git] / lnet / ulnds / socklnd / tcplnd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2002 Cray Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /* tcpnal.c:
23    This file implements the TCP-based nal by providing glue
24    between the connection service and the generic NAL implementation */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <syscall.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <pqtimer.h>
35 #include <dispatch.h>
36 #include <bridge.h>
37 #include <ipmap.h>
38 #include <connection.h>
39
40 /* Function:  tcpnal_send
41  * Arguments: nal:     pointer to my nal control block
42  *            private: unused
43  *            cookie:  passed back to the portals library
44  *            hdr:     pointer to the portals header
45  *            nid:     destination node
46  *            pid:     destination process
47  *            data:    body of the message
48  *            len:     length of the body
49  * Returns: zero on success
50  *
51  * sends a packet to the peer, after insuring that a connection exists
52  */
53 #warning FIXME: "param 'type' is newly added, make use of it!!"
54 int tcpnal_send(nal_cb_t *n,
55                 void *private,
56                 lib_msg_t *cookie,
57                 ptl_hdr_t *hdr,
58                 int type,
59                 ptl_nid_t nid,
60                 ptl_pid_t pid,
61                 unsigned int niov,
62                 struct iovec *iov,
63                 size_t len)
64 {
65     connection c;
66     bridge b=(bridge)n->nal_data;
67     struct iovec tiov[2];
68     int count = 1;
69
70     if (!(c=force_tcp_connection((manager)b->lower,
71                                  PNAL_IP(nid,b),
72                                  PNAL_PORT(nid,pid)))) 
73         return(1);
74
75 #if 0
76     /* TODO: these results should be checked. furthermore, provision
77        must be made for the SIGPIPE which is delivered when
78        writing on a tcp socket which has closed underneath
79        the application. there is a linux flag in the sendmsg
80        call which turns off the signally behaviour, but its
81        nonstandard */
82     syscall(SYS_write, c->fd,hdr,sizeof(ptl_hdr_t));
83     LASSERT (niov <= 1);
84     if (len) syscall(SYS_write, c->fd,iov[0].iov_base,len);
85 #else
86     LASSERT (niov <= 1);
87
88     tiov[0].iov_base = hdr;
89     tiov[0].iov_len = sizeof(ptl_hdr_t);
90
91     if (len) {
92             tiov[1].iov_base = iov[0].iov_base;
93             tiov[1].iov_len = len;
94             count++;
95     }
96
97     syscall(SYS_writev, c->fd, tiov, count);
98 #endif
99     lib_finalize(n, private, cookie);
100         
101     return(0);
102 }
103
104
105 /* Function:  tcpnal_recv
106  * Arguments: nal_cb_t *nal:     pointer to my nal control block
107  *            void *private:     connection pointer passed through
108  *                               lib_parse()
109  *            lib_msg_t *cookie: passed back to portals library
110  *            user_ptr data:     pointer to the destination buffer
111  *            size_t mlen:       length of the body
112  *            size_t rlen:       length of data in the network
113  * Returns: zero on success
114  *
115  * blocking read of the requested data. must drain out the
116  * difference of mainpulated and requested lengths from the network
117  */
118 int tcpnal_recv(nal_cb_t *n,
119                 void *private,
120                 lib_msg_t *cookie,
121                 unsigned int niov,
122                 struct iovec *iov,
123                 ptl_size_t mlen,
124                 ptl_size_t rlen)
125
126 {
127     if (mlen) {
128         LASSERT (niov <= 1);
129         read_connection(private,iov[0].iov_base,mlen);
130         lib_finalize(n, private, cookie);
131     }
132
133     if (mlen!=rlen){
134         char *trash=malloc(rlen-mlen);
135         
136         /*TODO: check error status*/
137         read_connection(private,trash,rlen-mlen);
138         free(trash);
139     }
140
141     return(rlen);
142 }
143
144
145 /* Function:  from_connection: 
146  * Arguments: c: the connection to read from 
147  * Returns: whether or not to continue reading from this connection,
148  *          expressed as a 1 to continue, and a 0 to not
149  *
150  *  from_connection() is called from the select loop when i/o is 
151  *  available. It attempts to read the portals header and 
152  *  pass it to the generic library for processing.
153  */
154 static int from_connection(void *a, void *d)
155 {
156         connection c = d;
157         bridge b=a;
158         ptl_hdr_t hdr;
159
160         if (read_connection(c, (unsigned char *)&hdr, sizeof(hdr))){
161                 lib_parse(b->nal_cb, &hdr, c);
162                 return(1);
163         }
164         return(0);
165 }
166
167
168 static void tcpnal_shutdown(bridge b)
169 {
170     shutdown_connections(b->lower);
171 }
172
173 /* Function:  PTL_IFACE_TCP
174  * Arguments: pid_request: desired port number to bind to
175  *            desired: passed NAL limits structure
176  *            actual: returned NAL limits structure
177  * Returns: a nal structure on success, or null on failure
178  */
179 int tcpnal_init(bridge b)
180 {
181     manager m;
182         
183     b->nal_cb->cb_send=tcpnal_send;
184     b->nal_cb->cb_recv=tcpnal_recv;
185     b->shutdown=tcpnal_shutdown;
186     
187     if (!(m=init_connections(PNAL_PORT(b->nal_cb->ni.nid,
188                                        b->nal_cb->ni.pid),
189                              from_connection,b))){
190         /* TODO: this needs to shut down the
191            newly created junk */
192         return(PTL_NAL_FAILED);
193     }
194     /* XXX cfs hack */
195     b->nal_cb->ni.pid=0;
196     b->lower=m;
197     return(PTL_OK);
198 }