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.


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