PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ps2ips.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
16/*
17
18NOTES:
19
20- recv/recvfrom/send/sendto are designed so that the data buffer can be misaligned, and the recv/send size is
21 not restricted to a multiple of 64 bytes. The implimentation method was borrowed from fileio
22 read/write code :P
23
24*/
25
26#include <types.h>
27#include <loadcore.h>
28#include <stdio.h>
29#include <sifman.h>
30#include <sifcmd.h>
31#include <sysclib.h>
32#include <thbase.h>
33#include <intrman.h>
34#include <ps2ip.h>
35#include <ps2ip_rpc.h>
36
37#define MODNAME "TCP/IP_Stack_RPC"
38IRX_ID(MODNAME, 1, 1);
39
40#define BUFF_SIZE (1024)
41
42#define MIN(a, b) (((a)<(b))?(a):(b))
43#define RDOWN_64(a) (((a) >> 6) << 6)
44
45static SifRpcDataQueue_t ps2ips_queue;
46static SifRpcServerData_t ps2ips_server;
47static u8 _rpc_buffer[512 * 4] __attribute__((__aligned__(4)));
48
49static char lwip_buffer[BUFF_SIZE + 32];
50static rests_pkt rests;
51
52static void do_accept( void * rpcBuffer, int size )
53{
54 int *ptr = rpcBuffer;
55 cmd_pkt *pkt = (cmd_pkt *)ptr;
56 struct sockaddr addr;
57 int addrlen, ret;
58
59 (void)size;
60
61 ret = accept(pkt->socket, &addr, &addrlen);
62
63 pkt->socket = ret;
64 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
65 pkt->len = sizeof(struct sockaddr);
66}
67
68static void do_bind( void * rpcBuffer, int size )
69{
70 int *ptr = rpcBuffer;
71 cmd_pkt *pkt = (cmd_pkt *)rpcBuffer;
72 int ret;
73
74 (void)size;
75
76 ret = bind(pkt->socket, &pkt->sockaddr, pkt->len);
77
78 ptr[0] = ret;
79}
80
81static void do_disconnect( void * rpcBuffer, int size )
82{
83 int *ptr = rpcBuffer;
84 int ret;
85
86 (void)size;
87
88 ret = disconnect(ptr[0]);
89
90 ptr[0] = ret;
91}
92
93static void do_connect( void * rpcBuffer, int size )
94{
95 int *ptr = rpcBuffer;
96 cmd_pkt *pkt = (cmd_pkt *)_rpc_buffer;
97 int ret;
98
99 (void)size;
100
101 ret = connect(pkt->socket, &pkt->sockaddr, pkt->len);
102
103 ptr[0] = ret;
104}
105
106static void do_listen( void * rpcBuffer, int size )
107{
108 int *ptr = rpcBuffer;
109 int ret;
110
111 (void)size;
112
113 ret = listen(ptr[0], ptr[1]);
114
115 ptr[0] = ret;
116}
117
118static void do_recv( void * rpcBuffer, int size )
119{
120 int srest, erest, asize; // size of unaligned portion, remainder portion, aligned portion
121 void *abuffer, *aebuffer; // aligned buffer start, aligned buffer end
122 int s_offset; // offset into lwip_buffer of srest data
123 int rlen, recvlen;
124 int dma_id = 0;
125 int intr_stat;
126 s_recv_pkt *recv_pkt = (s_recv_pkt *)rpcBuffer;
127 r_recv_pkt *ret_pkt = (r_recv_pkt *)rpcBuffer;
128 struct t_SifDmaTransfer sifdma;
129
130 (void)size;
131
132 if(recv_pkt->length <= 64)
133 {
134 srest = recv_pkt->length;
135
136 } else {
137
138 if( ((int)recv_pkt->ee_addr & 0x3F) == 0 ) // ee address is aligned
139 srest = 0;
140 else
141 srest = RDOWN_64((int)recv_pkt->ee_addr) - (int)recv_pkt->ee_addr + 64;
142 }
143
144 s_offset = 64 - srest;
145 recvlen = MIN(BUFF_SIZE, recv_pkt->length);
146
147 // Do actual TCP recv
148 rlen = recv(recv_pkt->socket, lwip_buffer + s_offset, recvlen, recv_pkt->flags);
149
150 if(rlen <= 0) goto recv_end;
151 if(rlen <= 64) srest = rlen;
152
153 // fill sbuffer, calculate align buffer & erest valules, fill ebuffer
154 if(srest)
155 memcpy((void *)rests.sbuffer, (void *)(lwip_buffer + s_offset), srest);
156
157 if(rlen > 64)
158 {
159 abuffer = recv_pkt->ee_addr + srest; // aligned buffer (round up)
160 aebuffer = (void *)RDOWN_64((int)recv_pkt->ee_addr + rlen); // aligned buffer end (round down)
161
162 asize = (int)aebuffer - (int)abuffer;
163
164 erest = recv_pkt->ee_addr + rlen - aebuffer;
165
166 if(erest)
167 memcpy((void *)rests.ebuffer, (void *)(lwip_buffer + 64 + asize), erest);
168
169// printf("srest = 0x%X\nabuffer = 0x%X\naebuffer = 0x%X\nasize = 0x%X\nerest = 0x%X\n", srest, abuffer, aebuffer, asize, erest);
170
171 } else {
172
173 abuffer = aebuffer = NULL;
174 erest = asize = 0;
175
176 }
177
178 // DMA back the abuffer
179 if(asize)
180 {
181 while(sceSifDmaStat(dma_id) >= 0);
182
183 sifdma.src = lwip_buffer + 64;
184 sifdma.dest = abuffer;
185 sifdma.size = asize;
186 sifdma.attr = 0;
187 CpuSuspendIntr(&intr_stat);
188 dma_id = sceSifSetDma(&sifdma, 1);
189 CpuResumeIntr(intr_stat);
190 }
191
192 // Fill rest of rests structure, dma back
193 rests.ssize = srest;
194 rests.esize = erest;
195 rests.sbuf = recv_pkt->ee_addr;
196 rests.ebuf = aebuffer;
197
198 while(sceSifDmaStat(dma_id) >= 0);
199
200 sifdma.src = &rests;
201 sifdma.dest = recv_pkt->intr_data;
202 sifdma.size = sizeof(rests_pkt);
203 sifdma.attr = 0;
204 CpuSuspendIntr(&intr_stat);
205 dma_id = sceSifSetDma(&sifdma, 1);
206 CpuResumeIntr(intr_stat);
207
208recv_end:
209 ret_pkt->ret = rlen;
210}
211
212static void do_recvfrom( void * rpcBuffer, int size )
213{
214 int srest, erest, asize; // size of unaligned portion, remainder portion, aligned portion
215 void *abuffer, *aebuffer; // aligned buffer start, aligned buffer end
216 int s_offset; // offset into lwip_buffer of srest data
217 int rlen, recvlen;
218 int dma_id = 0;
219 int intr_stat;
220 s_recv_pkt *recv_pkt = (s_recv_pkt *)rpcBuffer;
221 r_recv_pkt *ret_pkt = (r_recv_pkt *)rpcBuffer;
222 static struct t_SifDmaTransfer sifdma;
223 static struct sockaddr sockaddr;
224 int fromlen;
225
226 (void)size;
227
228 if(recv_pkt->length <= 64)
229 {
230 srest = recv_pkt->length;
231
232 } else {
233
234 if( ((int)recv_pkt->ee_addr & 0x3F) == 0 ) // ee address is aligned
235 srest = 0;
236 else
237 srest = RDOWN_64((int)recv_pkt->ee_addr) - (int)recv_pkt->ee_addr + 64;
238 }
239
240 s_offset = 64 - srest;
241 recvlen = MIN(BUFF_SIZE, recv_pkt->length);
242
243 // Do actual UDP recvfrom
244 rlen = recvfrom(recv_pkt->socket, lwip_buffer + s_offset, recvlen, recv_pkt->flags, &sockaddr, &fromlen);
245
246 if(rlen <= 0) goto recv_end;
247 if(rlen <= 64) srest = rlen;
248
249 // copy sockaddr struct to return packet
250 memcpy((void *)&ret_pkt->sockaddr, (void *)&sockaddr, sizeof(struct sockaddr));
251
252 // fill sbuffer, calculate align buffer & erest valules, fill ebuffer
253 if(srest)
254 memcpy((void *)rests.sbuffer, (void *)(lwip_buffer + s_offset), srest);
255
256 if(rlen > 64)
257 {
258 abuffer = recv_pkt->ee_addr + srest; // aligned buffer (round up)
259 aebuffer = (void *)RDOWN_64((int)recv_pkt->ee_addr + rlen); // aligned buffer end (round down)
260
261 asize = (int)aebuffer - (int)abuffer;
262
263 erest = recv_pkt->ee_addr + rlen - aebuffer;
264
265 if(erest)
266 memcpy((void *)rests.ebuffer, (void *)(lwip_buffer + 64 + asize), erest);
267
268// printf("srest = 0x%X\nabuffer = 0x%X\naebuffer = 0x%X\nasize = 0x%X\nerest = 0x%X\n", srest, abuffer, aebuffer, asize, erest);
269
270 } else {
271
272 abuffer = aebuffer = NULL;
273 erest = asize = 0;
274
275 }
276
277 // DMA back the abuffer
278 if(asize)
279 {
280 while(sceSifDmaStat(dma_id) >= 0);
281
282 sifdma.src = lwip_buffer + 64;
283 sifdma.dest = abuffer;
284 sifdma.size = asize;
285 sifdma.attr = 0;
286 CpuSuspendIntr(&intr_stat);
287 dma_id = sceSifSetDma(&sifdma, 1);
288 CpuResumeIntr(intr_stat);
289 }
290
291 // Fill rest of rests structure, dma back
292 rests.ssize = srest;
293 rests.esize = erest;
294 rests.sbuf = recv_pkt->ee_addr;
295 rests.ebuf = aebuffer;
296
297 while(sceSifDmaStat(dma_id) >= 0);
298
299 sifdma.src = &rests;
300 sifdma.dest = recv_pkt->intr_data;
301 sifdma.size = sizeof(rests_pkt);
302 sifdma.attr = 0;
303 CpuSuspendIntr(&intr_stat);
304 dma_id = sceSifSetDma(&sifdma, 1);
305 CpuResumeIntr(intr_stat);
306
307recv_end:
308 ret_pkt->ret = rlen;
309}
310
311static void do_send( void * rpcBuffer, int size )
312{
313 int *ptr = rpcBuffer;
314 send_pkt *pkt = (send_pkt *)rpcBuffer;
315 int slen, sendlen;
316 int s_offset; // offset into lwip_buffer for malign data
317 void *ee_pos;
319
320 (void)size;
321
322 if(pkt->malign)
323 {
324// printf("send: misaligned = %d\n", pkt->malign);
325
326 s_offset = 64 - pkt->malign;
327 memcpy((void *)(lwip_buffer + s_offset), pkt->malign_buff, pkt->malign);
328
329 } else s_offset = 64;
330
331 ee_pos = pkt->ee_addr + pkt->malign;
332
333 sendlen = MIN(BUFF_SIZE, pkt->length);
334
335 sceSifGetOtherData(&rdata, ee_pos, lwip_buffer + 64, sendlen - pkt->malign, 0);
336
337 // So actual TCP send
338 slen = send(pkt->socket, lwip_buffer + s_offset, sendlen, pkt->flags);
339
340 ptr[0] = slen;
341}
342
343
344static void do_sendto( void * rpcBuffer, int size )
345{
346 int *ptr = rpcBuffer;
347 send_pkt *pkt = (send_pkt *)rpcBuffer;
348 int slen, sendlen;
349 int s_offset; // offset into lwip_buffer for malign data
350 void *ee_pos;
352
353 (void)size;
354
355 if(pkt->malign)
356 {
357// printf("send: misaligned = %d\n", pkt->malign);
358
359 s_offset = 64 - pkt->malign;
360 memcpy((void *)(lwip_buffer + s_offset), pkt->malign_buff, pkt->malign);
361
362 } else s_offset = 64;
363
364 ee_pos = pkt->ee_addr + pkt->malign;
365
366 sendlen = MIN(BUFF_SIZE, pkt->length);
367
368 sceSifGetOtherData(&rdata, ee_pos, lwip_buffer + 64, sendlen - pkt->malign, 0);
369
370 // So actual UDP sendto
371 slen = sendto(pkt->socket, lwip_buffer + s_offset, sendlen, pkt->flags, &pkt->sockaddr, sizeof(struct sockaddr));
372
373 ptr[0] = slen;
374}
375
376static void do_socket( void * rpcBuffer, int size )
377{
378 int *ptr = rpcBuffer;
379 int ret;
380
381 (void)size;
382
383 ret = socket(ptr[0], ptr[1], ptr[2]);
384
385 ptr[0] = ret;
386}
387
388static void do_getconfig(void *rpcBuffer, int size)
389{
390 (void)size;
391
392 ps2ip_getconfig((char *)rpcBuffer, (t_ip_info *)rpcBuffer);
393}
394
395static void do_setconfig(void *rpcBuffer, int size)
396{
397 (void)size;
398
399 ps2ip_setconfig((t_ip_info *)rpcBuffer);
400}
401
402static void do_select( void * rpcBuffer, int size )
403{
404 select_pkt *pkt = (select_pkt*)_rpc_buffer;
405
406 (void)rpcBuffer;
407 (void)size;
408
409 pkt->result = select( pkt->maxfdp1,
410 pkt->readset_p != NULL ? &pkt->readset : NULL,
411 pkt->writeset_p != NULL ? &pkt->writeset : NULL,
412 pkt->exceptset_p != NULL ? &pkt->exceptset : NULL,
413 pkt->timeout_p != NULL ? &pkt->timeout : NULL );
414}
415
416static void do_ioctlsocket( void *rpcBuffer, int size )
417{
418 ioctl_pkt *pkt = (ioctl_pkt*)_rpc_buffer;
419
420 (void)rpcBuffer;
421 (void)size;
422
423 pkt->result = ioctlsocket( pkt->s,
424 pkt->cmd,
425 pkt->argp != NULL ? &pkt->value : NULL );
426}
427static void do_getsockname( void *rpcBuffer, int size )
428{
429 int *ptr = rpcBuffer;
430 cmd_pkt *pkt = (cmd_pkt *)ptr;
431 struct sockaddr addr;
432 int addrlen, ret;
433
434 (void)size;
435
436 ret = getsockname(pkt->socket, &addr, &addrlen);
437
438 pkt->socket = ret;
439 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
440 pkt->len = sizeof(struct sockaddr);
441}
442
443static void do_getpeername( void *rpcBuffer, int size )
444{
445 int *ptr = rpcBuffer;
446 cmd_pkt *pkt = (cmd_pkt *)ptr;
447 struct sockaddr addr;
448 int addrlen, ret;
449
450 (void)size;
451
452 ret = getpeername(pkt->socket, &addr, &addrlen);
453
454 pkt->socket = ret;
455 memcpy(&pkt->sockaddr, &addr, sizeof(struct sockaddr));
456 pkt->len = sizeof(struct sockaddr);
457}
458
459static void do_getsockopt( void *rpcBuffer, int size )
460{
461 int ret, s, level, optname, optlen;
462 unsigned char optval[128];
463
464 (void)size;
465
466 s = ((getsockopt_pkt*)rpcBuffer)->s;
467 level = ((getsockopt_pkt*)rpcBuffer)->level;
468 optname = ((getsockopt_pkt*)rpcBuffer)->optname;
469 optlen = sizeof(optval);
470
471 ret = getsockopt(s, level, optname, optval, &optlen);
472
473 ((getsockopt_res_pkt*)rpcBuffer)->result = ret;
474 ((getsockopt_res_pkt*)rpcBuffer)->optlen = optlen;
475 memcpy( ((getsockopt_res_pkt*)rpcBuffer)->buffer, optval, 128 );
476}
477
478static void do_setsockopt( void *rpcBuffer, int size )
479{
480 int *ptr = rpcBuffer, ret;
481 int s;
482 int level;
483 int optname;
484 int optlen;
485 unsigned char optval[128];
486
487 (void)size;
488
489 s = ((setsockopt_pkt*)rpcBuffer)->s;
490 level = ((setsockopt_pkt*)rpcBuffer)->level;
491 optname = ((setsockopt_pkt*)rpcBuffer)->optname;
492 optlen = ((setsockopt_pkt*)rpcBuffer)->optlen;
493 memcpy(optval, ((setsockopt_pkt*)rpcBuffer)->buffer, optlen);
494
495 ret = setsockopt(s, level, optname, optval, optlen);
496 ptr[0] = ret;
497}
498
499#ifdef PS2IP_DNS
500static void do_gethostbyname( void *rpcBuffer, int size )
501{
502 struct hostent *ret;
503 gethostbyname_res_pkt *resPtr = rpcBuffer;
504
505 (void)size;
506
507 if((ret = gethostbyname((char*)_rpc_buffer)) != NULL)
508 {
509 resPtr->result = 0;
510 resPtr->hostent.h_addrtype = ret->h_addrtype;
511 resPtr->hostent.h_length = ret->h_length;
512 memcpy(&resPtr->hostent.h_addr, &ret->h_addr_list[0], sizeof(resPtr->hostent.h_addr));
513 }else{
514 resPtr->result = -1;
515 }
516}
517
518static void do_dns_setserver( void *rpcBuffer, int size )
519{
520 (void)rpcBuffer;
521 (void)size;
522
523 dns_setserver(((dns_setserver_pkt*)_rpc_buffer)->numdns, &((dns_setserver_pkt*)_rpc_buffer)->dnsserver);
524}
525
526static void do_dns_getserver( void *rpcBuffer, int size )
527{
528 const ip_addr_t *dns;
529
530 (void)size;
531
532 dns = dns_getserver(*(u8*)_rpc_buffer);
533 ip_addr_copy(((dns_getserver_res_pkt*)rpcBuffer)->dnsserver, *dns);
534}
535#endif
536
537static void * rpcHandlerFunction(unsigned int command, void * rpcBuffer, int size)
538{
539 switch(command)
540 {
541 case PS2IPS_ID_ACCEPT:
542 do_accept(rpcBuffer, size);
543 break;
544 case PS2IPS_ID_BIND:
545 do_bind(rpcBuffer, size);
546 break;
547 case PS2IPS_ID_DISCONNECT:
548 do_disconnect(rpcBuffer, size);
549 break;
550 case PS2IPS_ID_CONNECT:
551 do_connect(rpcBuffer, size);
552 break;
553 case PS2IPS_ID_LISTEN:
554 do_listen(rpcBuffer, size);
555 break;
556 case PS2IPS_ID_RECV:
557 do_recv(rpcBuffer, size);
558 break;
559 case PS2IPS_ID_RECVFROM:
560 do_recvfrom(rpcBuffer, size);
561 break;
562 case PS2IPS_ID_SEND:
563 do_send(rpcBuffer, size);
564 break;
565 case PS2IPS_ID_SENDTO:
566 do_sendto(rpcBuffer, size);
567 break;
568 case PS2IPS_ID_SOCKET:
569 do_socket(rpcBuffer, size);
570 break;
571 case PS2IPS_ID_GETCONFIG:
572 do_getconfig(rpcBuffer, size);
573 break;
574 case PS2IPS_ID_SETCONFIG:
575 do_setconfig(rpcBuffer, size);
576 break;
577 case PS2IPS_ID_SELECT:
578 do_select(rpcBuffer, size);
579 break;
580 case PS2IPS_ID_IOCTL:
581 do_ioctlsocket(rpcBuffer, size);
582 break;
583 case PS2IPS_ID_GETSOCKNAME:
584 do_getsockname(rpcBuffer, size);
585 break;
586 case PS2IPS_ID_GETPEERNAME:
587 do_getpeername(rpcBuffer, size);
588 break;
589 case PS2IPS_ID_GETSOCKOPT:
590 do_getsockopt(rpcBuffer, size);
591 break;
592 case PS2IPS_ID_SETSOCKOPT:
593 do_setsockopt(rpcBuffer, size);
594 break;
595#ifdef PS2IP_DNS
596 case PS2IPS_ID_GETHOSTBYNAME:
597 do_gethostbyname(rpcBuffer, size);
598 break;
599 case PS2IPS_ID_DNS_SETSERVER:
600 do_dns_setserver(rpcBuffer, size);
601 break;
602 case PS2IPS_ID_DNS_GETSERVER:
603 do_dns_getserver(rpcBuffer, size);
604 break;
605#endif
606 default:
607 printf("PS2IPS: Unknown Function called!\n");
608
609 }
610
611 return rpcBuffer;
612}
613
614static void threadRpcFunction(void *arg)
615{
616 (void)arg;
617
618 printf("PS2IPS: RPC Thread Started\n");
619
620 sceSifSetRpcQueue( &ps2ips_queue , GetThreadId() );
621 sceSifRegisterRpc( &ps2ips_server, PS2IP_IRX, (void *)rpcHandlerFunction,(u8 *)&_rpc_buffer,NULL,NULL, &ps2ips_queue );
622 sceSifRpcLoop( &ps2ips_queue );
623}
624
625int _start( int argc, char *argv[])
626{
627 int threadId;
628 iop_thread_t t;
629
630 (void)argc;
631 (void)argv;
632
633 printf( "PS2IPS: Module Loaded.\n" );
634
635 t.attr = TH_C;
636 t.option = 0;
637 t.thread = &threadRpcFunction;
638 t.stacksize = 0x800;
639 t.priority = 0x1e;
640
641 threadId = CreateThread( &t );
642 if ( threadId < 0 )
643 {
644 printf( "PS2IPS: CreateThread failed. %i\n", threadId );
645 return MODULE_NO_RESIDENT_END;
646 }
647 else
648 {
649 StartThread( threadId, NULL );
650 return MODULE_RESIDENT_END;
651 }
652}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
typedef __attribute__
Definition tlbfunc.c:60
u8 malign_buff[64]
Definition ps2ip_rpc.h:75