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.


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