Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


a3966e19fd4165905c89e3d83b7e0300ed1fc01e
[palacios.git] / palacios / src / geekos / socket.c
1 #include <geekos/socket.h>
2 #include <geekos/malloc.h>
3 #include <geekos/ne2k.h>
4 #include <uip/uip.h>
5 #include <uip/uip_arp.h>
6 #include <geekos/vmm_stubs.h>
7 #include <geekos/debug.h>
8
9
10
11 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
12
13 #define MAX_SOCKS 1024
14 #define BUF_SIZE 1000
15
16 struct socket sockets[MAX_SOCKS];
17
18
19
20 int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
21
22 void init_network() {
23    int i = 0;
24    
25    for (i = 0; i < MAX_SOCKS; i++) {
26       sockets[i].in_use = 0;
27       sockets[i].send_buf = NULL;
28       sockets[i].recv_buf = NULL;
29       sockets[i].state = CLOSED;
30    }
31
32
33     //initiate uIP
34     uip_init();
35     uip_arp_init();
36         
37     //setup device driver
38     Init_Ne2k(&Packet_Received);
39
40
41
42 }
43
44
45
46
47 void set_ip_addr(uchar_t addr[4]) {
48   uip_ipaddr_t ipaddr;
49   uip_ipaddr(ipaddr, addr[0], addr[1], addr[2], addr[3]);  /* Local IP address */
50   uip_sethostaddr(ipaddr);
51 }
52
53
54 static int allocate_socket_fd() {
55   int i = 0;
56   
57   for (i = 0; i < MAX_SOCKS; i++) {
58     if (sockets[i].in_use == 0) {
59       sockets[i].in_use = 1;
60       sockets[i].send_buf = create_ring_buffer(BUF_SIZE);
61       if (sockets[i].send_buf == NULL)
62                 return -1;
63       sockets[i].recv_buf = create_ring_buffer(BUF_SIZE);
64       if (sockets[i].recv_buf == NULL){
65                 free_ring_buffer(sockets[i].send_buf);
66                 return -1;
67       }
68       return i;
69     }
70   }
71
72   return -1;
73 }
74
75 static int release_socket_fd(int sockfd){
76        if (sockfd >= 0 && sockfd < MAX_SOCKS){
77                 sockets[sockfd].in_use = 0;
78                 free_ring_buffer(sockets[sockfd].send_buf);
79                 free_ring_buffer(sockets[sockfd].recv_buf);
80                 sockets[sockfd].send_buf = NULL;
81                 sockets[sockfd].recv_buf = NULL;
82                 sockets[sockfd].state = CLOSED;
83        }
84
85         return 0;
86 }
87
88
89 struct socket * get_socket_from_fd(int fd) {
90   return &(sockets[fd]);
91 }
92
93
94 int connect(const uchar_t ip_addr[4], ushort_t port) {
95   int sockfd = -1;
96   sockfd = allocate_socket_fd();
97   uip_ipaddr_t ipaddr;
98   
99   if (sockfd == -1) {
100     return -1;
101   }
102
103   uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);  
104
105   sockets[sockfd].state = WAITING;
106   
107   sockets[sockfd].con = uip_connect((uip_ipaddr_t *)&ip_addr, htons(port));
108
109
110   if (sockets[sockfd].con == NULL){
111     release_socket_fd(sockfd);
112     return -1;
113   }
114
115
116   PrintBoth("Connection start\n");
117
118   while(sockets[sockfd].state == WAITING) {
119     timer_int_handler(NULL);
120   }
121
122     
123   PrintBoth("Connected\n");
124
125   if (sockets[sockfd].state != ESTABLISHED) {
126     release_socket_fd(sockfd);
127     return -1;
128   }
129
130
131   return sockfd;
132 }
133
134 int recv(int sockfd, void * buf, uint_t len){
135   uint_t recvlen;
136
137   struct socket *sock = get_socket_from_fd(sockfd);
138
139
140   // here we need some lock mechnism, just disable interrupt may not work properly because recv() will be run as a kernel thread 
141 buf_read:
142   recvlen = rb_read(sock->recv_buf, buf, len);
143
144   if (recvlen == 0){
145         Wait(&(sock->recv_wait_queue));
146         goto buf_read;
147   }
148
149   return recvlen;
150 }
151
152 void timer_int_Handler(struct Interrupt_State * state){
153         int i;
154         //handle the periodic calls of uIP
155         for(i = 0; i < UIP_CONNS; ++i) {
156                uip_periodic(i);
157                 if(uip_len > 0) {
158                      //devicedriver_send();
159                      NE2K_Transmit(uip_len);
160                 }
161         }
162         for(i = 0; i < UIP_UDP_CONNS; i++) {
163                  uip_udp_periodic(i);
164                  if(uip_len > 0) {
165                      //devicedriver_send();
166                      NE2K_Transmit(uip_len);
167                 }
168         }
169 }
170
171 // a series of utilities to handle conncetion states
172 static void connected(int sockfd) {
173   struct socket * sock = get_socket_from_fd(sockfd);
174
175   PrintBoth("Connected Interrupt\n");
176
177   sock->state = ESTABLISHED;
178
179   Wake_Up(&(sock->recv_wait_queue));
180 }
181
182 static void closed(int sockfd){
183
184 }
185
186 static void acked(int sockfd){
187
188 }
189
190 static void newdata(int sockfd){
191   uint_t len;
192   char *dataptr;
193   uint_t wrlen;
194   struct socket *sock;
195     
196   len = uip_datalen();
197   dataptr = (char *)uip_appdata;
198
199   if (len == 0)
200         return;
201
202   sock = get_socket_from_fd(sockfd);
203
204   wrlen = rb_write(sock->recv_buf, dataptr, len);
205
206   if (wrlen < len){ //write error, what should I do?
207         return;
208   }
209
210   Wake_Up(&(sock->recv_wait_queue));
211
212   return;    
213
214 }
215
216 // not finished yet
217 static void send_to_driver(int sockfd) {
218
219   PrintBoth("Sending data to driver\n");
220
221 }
222
223
224
225 int send(int sockfd, void * buf, uint_t len) {
226   struct socket * sock = get_socket_from_fd(sockfd);
227   //int mss = uip_mss();
228   //int pending_bytes = rb_data_len(sock->send_buf);
229   //int len = (mss < pending_bytes) ? mss: pending_bytes;
230   int bytes_read = 0;
231   uchar_t * send_buf = uip_appdata;
232   
233   bytes_read = rb_peek(sock->send_buf, send_buf, len);
234
235   if (bytes_read == 0) {
236     // no packet for send
237     return -1;
238   }
239
240   uip_send(send_buf, len);
241
242   return len;
243 }
244
245
246
247 //get the socket id by the local tcp port
248 static int get_socket_from_port(ushort_t lport) {
249   int i;
250   
251
252   for (i = 0; i < MAX_SOCKS; i++){
253     if (sockets[i].con->lport == lport) {
254       return i;
255     }
256   }
257   
258   return -1;
259 }
260
261
262
263 void socket_appcall(void) {
264
265   int sockfd; 
266   
267   sockfd = get_socket_from_port(uip_conn->lport);
268
269   PrintBoth("Appcall\n");
270
271   
272   if (sockfd == -1) {
273     return;
274   }
275
276   if (uip_connected()) {
277     connected(sockfd);
278
279   }
280   
281   if (uip_closed() ||uip_aborted() ||uip_timedout()) {
282      closed(sockfd);
283      return;
284   }
285   
286   if (uip_acked()) {
287      acked(sockfd);
288   }
289   
290   if (uip_newdata()) {
291      newdata(sockfd);
292   }
293   
294   if (uip_rexmit() ||
295       uip_newdata() ||
296       uip_acked() ||
297       uip_connected() ||
298       uip_poll()) {
299     send_to_driver(sockfd);
300   }
301 }
302
303
304
305
306 int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
307   //int i;
308   
309   uip_len = info->size; 
310
311   //  for (i = 0; i < info->size; i++) {
312   //  uip_buf[i] = *(pkt + i);
313   //}
314
315   memcpy(uip_buf, pkt, uip_len);
316
317
318   Free(pkt);
319
320   if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
321     uip_arp_arpin();
322
323     if (uip_len > 0) {
324       NE2K_Transmit(uip_len);
325     }                                   
326
327   } else {
328
329     uip_arp_ipin();
330     uip_input();
331
332     if (uip_len > 0) {
333       uip_arp_out();
334       NE2K_Transmit(uip_len);
335     }
336   }
337                           
338   return 0;
339
340 }