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.


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