Subversion Repositories Kolibri OS

Rev

Rev 3600 | Rev 3602 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
$Revision: 3514 $
19
 
20
 
21
struct  SOCKET
22
 
23
        NextPtr                 dd ? ; pointer to next socket in list
24
        PrevPtr                 dd ? ; pointer to previous socket in list
25
        Number                  dd ? ; socket number
26
 
27
        mutex                   MUTEX
28
 
29
        PID                     dd ? ; process ID
30
        TID                     dd ? ; thread ID
31
        Domain                  dd ? ; INET/LOCAL/..
32
        Type                    dd ? ; RAW/STREAM/DGRAP
33
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
34
        errorcode               dd ?
35
        device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
36
 
37
        options                 dd ?
38
        state                   dd ?
39
        backlog                 dw ? ; how many incoming connections that can be queued
40
 
41
        snd_proc                dd ?
42
        rcv_proc                dd ?
43
 
44
ends
45
 
46
struct  IP_SOCKET               SOCKET
47
 
48
        LocalIP                 rd 4 ; network byte order
49
        RemoteIP                rd 4 ; network byte order
50
 
51
ends
52
 
53
struct  TCP_SOCKET              IP_SOCKET
54
 
55
        LocalPort               dw ? ; network byte order
56
        RemotePort              dw ? ; network byte order
57
 
58
        t_state                 dd ? ; TCB state
59
        t_rxtshift              db ?
60
                                rb 3 ; align
61
        t_rxtcur                dd ?
62
        t_dupacks               dd ?
63
        t_maxseg                dd ?
64
        t_force                 dd ?
65
        t_flags                 dd ?
66
 
67
;---------------
68
; RFC783 page 21
69
 
70
; send sequence
71
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
72
        SND_NXT                 dd ? ; next send sequence number to use
73
        SND_UP                  dd ? ; urgent pointer
74
        SND_WL1                 dd ? ; window minus one
75
        SND_WL2                 dd ? ;
76
        ISS                     dd ? ; initial send sequence number
77
        SND_WND                 dd ? ; send window
78
 
79
; receive sequence
80
        RCV_WND                 dd ? ; receive window
81
        RCV_NXT                 dd ? ; next receive sequence number to use
82
        RCV_UP                  dd ? ; urgent pointer
83
        IRS                     dd ? ; initial receive sequence number
84
 
85
;---------------------
86
; Additional variables
87
 
88
; receive variables
89
        RCV_ADV                 dd ?
90
 
91
; retransmit variables
92
        SND_MAX                 dd ?
93
 
94
; congestion control
95
        SND_CWND                dd ?
96
        SND_SSTHRESH            dd ?
97
 
98
;----------------------
99
; Transmit timing stuff
100
        t_idle                  dd ?
101
        t_rtt                   dd ?
102
        t_rtseq                 dd ?
103
        t_srtt                  dd ?
104
        t_rttvar                dd ?
105
        t_rttmin                dd ?
106
        max_sndwnd              dd ?
107
 
108
;-----------------
109
; Out-of-band data
110
        t_oobflags              dd ?
111
        t_iobc                  dd ?
112
        t_softerror             dd ?
113
 
114
 
115
;---------
116
; RFC 1323                              ; the order of next 4 elements may not change
117
 
118
        SND_SCALE               db ?
119
        RCV_SCALE               db ?
120
        requested_s_scale       db ?
121
        request_r_scale         db ?
122
 
123
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
124
        ts_recent_age           dd ?
125
        last_ack_sent           dd ?
126
 
127
 
128
;-------
129
; Timers
3600 hidnplayr 130
        timer_flags             dd ?
3545 hidnplayr 131
        timer_retransmission    dd ? ; rexmt
132
        timer_persist           dd ?
133
        timer_keepalive         dd ? ; keepalive/syn timeout
134
        timer_timed_wait        dd ? ; also used as 2msl timer
135
 
136
; extra
137
 
138
        ts_ecr                  dd ? ; timestamp echo reply
139
        ts_val                  dd ?
140
 
141
        seg_next                dd ? ; re-assembly queue
142
 
143
        temp_bits               db ?
144
                                rb 3 ; align
145
 
146
ends
147
 
148
struct  UDP_SOCKET              IP_SOCKET
149
 
150
        LocalPort               dw ? ; network byte order
151
        RemotePort              dw ? ; network byte order
152
        firstpacket             db ?
153
 
154
ends
155
 
156
 
157
struct  ICMP_SOCKET             IP_SOCKET
158
 
159
        Identifier              dw ?
160
 
161
ends
162
 
163
 
164
struct  RING_BUFFER
165
 
166
        mutex                   MUTEX
167
        start_ptr               dd ? ; Pointer to start of buffer
168
        end_ptr                 dd ? ; pointer to end of buffer
169
        read_ptr                dd ? ; Read pointer
170
        write_ptr               dd ? ; Write pointer
171
        size                    dd ? ; Number of bytes buffered
172
 
173
ends
174
 
175
struct  STREAM_SOCKET           TCP_SOCKET
176
 
177
        rcv                     RING_BUFFER
178
        snd                     RING_BUFFER
179
 
180
ends
181
 
182
struct  socket_queue_entry
183
 
184
        data_ptr                dd ?
185
        buf_ptr                 dd ?
186
        data_size               dd ?
187
 
188
ends
189
 
190
 
191
SOCKETBUFFSIZE          = 4096     ; in bytes
192
 
193
SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
194
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
195
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
196
 
197
uglobal
198
        net_sockets     rd 4
199
        last_socket_num dd ?
200
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
201
        last_TCP_port   dw ? ;
202
endg
203
 
204
 
205
;-----------------------------------------------------------------
206
;
207
; SOCKET_init
208
;
209
;-----------------------------------------------------------------
210
macro   SOCKET_init {
211
 
212
        xor     eax, eax
213
        mov     edi, net_sockets
214
        mov     ecx, 5
215
        rep     stosd
216
 
217
       @@:
218
        pseudo_random eax
3600 hidnplayr 219
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 220
        jb      @r
3600 hidnplayr 221
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 222
        ja      @r
223
        xchg    al, ah
224
        mov     [last_UDP_port], ax
225
 
226
       @@:
227
        pseudo_random eax
3600 hidnplayr 228
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 229
        jb      @r
3600 hidnplayr 230
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 231
        ja      @r
232
        xchg    al, ah
233
        mov     [last_TCP_port], ax
234
 
235
}
236
 
237
;-----------------------------------------------------------------
238
;
239
; Socket API (function 74)
240
;
241
;-----------------------------------------------------------------
242
align 4
243
sys_socket:
244
 
245
        cmp     ebx, 255
246
        jz      SOCKET_debug
247
 
248
        cmp     ebx, .number
249
        ja      s_error
250
        jmp     dword [.table + 4*ebx]
251
 
252
  .table:
253
        dd      SOCKET_open     ; 0
254
        dd      SOCKET_close    ; 1
255
        dd      SOCKET_bind     ; 2
256
        dd      SOCKET_listen   ; 3
257
        dd      SOCKET_connect  ; 4
258
        dd      SOCKET_accept   ; 5
259
        dd      SOCKET_send     ; 6
260
        dd      SOCKET_receive  ; 7
261
        dd      SOCKET_set_opt  ; 8
262
        dd      SOCKET_get_opt  ; 9
263
        dd      SOCKET_pair     ; 10
264
  .number = ($ - .table) / 4 - 1
265
 
266
s_error:
3556 hidnplayr 267
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET: error\n"
3545 hidnplayr 268
        mov     dword [esp+32], -1
269
 
270
        ret
271
 
272
;-----------------------------------------------------------------
273
;
274
; SOCKET_open
275
;
276
;  IN:  domain in ecx
277
;       type in edx
278
;       protocol in esi
279
;  OUT: eax is socket num, -1 on error
280
;
281
;-----------------------------------------------------------------
282
align 4
283
SOCKET_open:
284
 
3556 hidnplayr 285
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3545 hidnplayr 286
 
287
        push    ecx edx esi
288
        call    SOCKET_alloc
289
        pop     esi edx ecx
290
        jz      s_error
291
 
292
        mov     [esp+32], edi                   ; return socketnumber
3556 hidnplayr 293
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3545 hidnplayr 294
 
295
;        push    edx
296
;        and     edx, SO_NONBLOCK
297
        or      [eax + SOCKET.options], SO_NONBLOCK ;edx
298
;        pop     edx
299
;        and     edx, not SO_NONBLOCK
300
 
301
        mov     [eax + SOCKET.Domain], ecx
302
        mov     [eax + SOCKET.Type], edx
303
        mov     [eax + SOCKET.Protocol], esi
304
 
305
        cmp     ecx, AF_INET4
306
        jne     .no_inet4
307
 
308
        cmp     edx, SOCK_DGRAM
309
        je      .udp
310
 
311
        cmp     edx, SOCK_STREAM
312
        je      .tcp
313
 
314
        cmp     edx, SOCK_RAW
315
        je      .raw
316
 
317
  .no_inet4:
318
        cmp     ecx, AF_PPP
319
        jne     .no_ppp
320
 
321
        cmp     esi, PPP_PROTO_ETHERNET
322
        je      .pppoe
323
 
324
  .no_ppp:
3556 hidnplayr 325
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n"
3545 hidnplayr 326
        ret
327
 
328
align 4
329
  .raw:
330
        test    esi, esi       ; IP_PROTO_IP
331
        jz      .ip
332
 
333
        cmp     esi, IP_PROTO_ICMP
334
        je      .icmp
335
 
336
        cmp     esi, IP_PROTO_UDP
337
        je      .udp
338
 
339
        cmp     esi, IP_PROTO_TCP
340
        je      .tcp
341
 
342
        ret
343
 
344
align 4
345
  .udp:
346
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
347
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
348
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
349
        ret
350
 
351
align 4
352
  .tcp:
353
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
354
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
355
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
356
 
357
        TCP_init_socket eax
358
        ret
359
 
360
 
361
align 4
362
  .ip:
363
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
364
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
365
        ret
366
 
367
 
368
align 4
369
  .icmp:
370
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
371
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
372
        ret
373
 
374
align 4
375
  .pppoe:
376
        push    eax
377
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
378
        pop     eax
379
 
380
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
381
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
382
        ret
383
 
384
 
385
;-----------------------------------------------------------------
386
;
387
; SOCKET_bind
388
;
389
;  IN:  socket number in ecx
390
;       pointer to sockaddr struct in edx
391
;       length of that struct in esi
392
;  OUT: 0 on success
393
;
394
;-----------------------------------------------------------------
395
align 4
396
SOCKET_bind:
397
 
3556 hidnplayr 398
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 399
 
400
        call    SOCKET_num_to_ptr
401
        jz      s_error
402
 
403
        cmp     esi, 2
404
        jb      s_error
405
 
406
        cmp     word [edx], AF_INET4
407
        je      .af_inet4
408
 
409
        cmp     word [edx], AF_LOCAL
410
        je      .af_local
411
 
412
        jmp     s_error
413
 
414
  .af_local:
415
        ; TODO: write code here
416
 
417
        mov     dword [esp+32], 0
418
        ret
419
 
420
  .af_inet4:
421
 
422
        cmp     esi, 6
423
        jb      s_error
424
 
425
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
426
        je      .udp
427
 
428
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
429
        je      .tcp
430
 
431
        jmp     s_error
432
 
433
  .tcp:
434
  .udp:
435
 
3601 hidnplayr 436
        cmp     ebx, [edx + 4]                  ; First, fill in the IP
3545 hidnplayr 437
        test    ebx, ebx                        ; If IP is 0, use default
438
        jnz     @f
3601 hidnplayr 439
        mov     ebx, [IP_LIST + 4]      ;;;;; FIXME !i!i!i
3545 hidnplayr 440
       @@:
441
        mov     [eax + IP_SOCKET.LocalIP], ebx
442
 
443
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
444
        call    SOCKET_check_port
445
        jz      s_error                         ; ZF is set by socket_check_port, on error
446
 
3556 hidnplayr 447
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3545 hidnplayr 448
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
449
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
450
 
451
        mov     dword [esp+32], 0
452
        ret
453
 
454
 
455
 
456
 
457
;-----------------------------------------------------------------
458
;
459
; SOCKET_connect
460
;
461
;  IN:  socket number in ecx
462
;       pointer to sockaddr struct in edx
463
;       length of that struct in esi
464
;  OUT: 0 on success
465
;
466
;-----------------------------------------------------------------
467
align 4
468
SOCKET_connect:
469
 
3556 hidnplayr 470
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 471
 
472
        call    SOCKET_num_to_ptr
473
        jz      s_error
474
 
475
        cmp     esi, 8
476
        jb      s_error
477
 
478
        cmp     word [edx], AF_INET4
479
        je      .af_inet4
480
 
481
        jmp     s_error
482
 
483
  .af_inet4:
484
        cmp     [eax + IP_SOCKET.LocalIP], 0
485
        jne     @f
3601 hidnplayr 486
        push    [IP_LIST + 4]                               ; FIXME !i!i!i!
3545 hidnplayr 487
        pop     [eax + IP_SOCKET.LocalIP]
488
       @@:
489
 
490
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
491
        je      .udp
492
 
493
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
494
        je      .tcp
495
 
496
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
497
        je      .ip
498
 
499
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
500
        je      .ip
501
 
502
        jmp     s_error
503
 
504
align 4
505
  .udp:
506
        pusha
507
        lea     ecx, [eax + SOCKET.mutex]
508
        call    mutex_lock
509
        popa
510
 
511
        pushw   [edx + 2]
512
        pop     [eax + UDP_SOCKET.RemotePort]
513
 
514
        pushd   [edx + 4]
515
        pop     [eax + IP_SOCKET.RemoteIP]
516
 
3601 hidnplayr 517
        DEBUGF  1, "Connecting to 0x%x\n", [eax + IP_SOCKET.RemoteIP]
518
 
3545 hidnplayr 519
        cmp     [eax + UDP_SOCKET.LocalPort], 0
520
        jne     @f
521
        call    SOCKET_find_port
522
       @@:
523
 
524
        mov     [eax + UDP_SOCKET.firstpacket], 0
525
 
526
        push    eax
527
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
528
        pop     eax
529
 
530
        lea     ecx, [eax + SOCKET.mutex]
531
        call    mutex_unlock
532
 
533
        mov     dword [esp+32], 0
534
        ret
535
 
536
align 4
537
  .tcp:
538
        pusha
539
        lea     ecx, [eax + SOCKET.mutex]
540
        call    mutex_lock
541
        popa
542
 
543
        pushw   [edx + 2]
544
        pop     [eax + TCP_SOCKET.RemotePort]
545
 
546
        pushd   [edx + 4]
547
        pop     [eax + IP_SOCKET.RemoteIP]
548
 
549
        cmp     [eax + TCP_SOCKET.LocalPort], 0
550
        jne     @f
551
        call    SOCKET_find_port
552
       @@:
553
 
554
        mov     [eax + TCP_SOCKET.timer_persist], 0
555
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
556
 
557
        push    [TCP_sequence_num]
558
        add     [TCP_sequence_num], 6400
559
        pop     [eax + TCP_SOCKET.ISS]
560
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
561
 
562
 
563
        TCP_sendseqinit eax
564
 
565
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
566
 
567
        mov     ebx, eax
568
 
569
        lea     eax, [ebx + STREAM_SOCKET.snd]
570
        call    SOCKET_ring_create
571
 
572
        lea     eax, [ebx + STREAM_SOCKET.rcv]
573
        call    SOCKET_ring_create
574
 
575
        pusha
576
        lea     ecx, [ebx + SOCKET.mutex]
577
        call    mutex_unlock
578
        popa
579
 
580
        mov     eax, ebx
581
        call    TCP_output
582
 
583
;;; TODO: wait for successfull connection if blocking socket
584
 
585
        mov     dword [esp+32], 0
586
        ret
587
 
588
align 4
589
  .ip:
590
        pusha
591
        lea     ecx, [eax + SOCKET.mutex]
592
        call    mutex_lock
593
        popa
594
 
595
        pushd   [edx + 4]
596
        pop     [eax + IP_SOCKET.RemoteIP]
597
 
598
        push    eax
599
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
600
        pop     eax
601
 
602
        lea     ecx, [eax + SOCKET.mutex]
603
        call    mutex_unlock
604
 
605
        mov     dword [esp+32], 0
606
        ret
607
 
608
 
609
;-----------------------------------------------------------------
610
;
611
; SOCKET_listen
612
;
613
;  IN:  socket number in ecx
614
;       backlog in edx
615
;  OUT: eax is socket num, -1 on error
616
;
617
;-----------------------------------------------------------------
618
align 4
619
SOCKET_listen:
620
 
3556 hidnplayr 621
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 622
 
623
        call    SOCKET_num_to_ptr
624
        jz      s_error
625
 
626
        cmp     [eax + SOCKET.Domain], AF_INET4
627
        jne     s_error
628
 
629
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
630
        jne     s_error
631
 
632
        cmp     [eax + TCP_SOCKET.LocalPort], 0
633
        je      s_error
634
 
635
        cmp     [eax + IP_SOCKET.LocalIP], 0
636
        jne     @f
3601 hidnplayr 637
        push    [IP_LIST + 4]           ;;; fixme!!!!
3545 hidnplayr 638
        pop     [eax + IP_SOCKET.LocalIP]
639
       @@:
640
 
641
        cmp     edx, MAX_backlog
642
        jbe     @f
643
        mov     edx, MAX_backlog
644
       @@:
645
 
646
        mov     [eax + SOCKET.backlog], dx
647
        or      [eax + SOCKET.options], SO_ACCEPTCON
648
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
649
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
650
 
651
        push    eax
652
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
653
        pop     eax
654
 
655
        mov     dword [esp+32], 0
656
 
657
        ret
658
 
659
 
660
;-----------------------------------------------------------------
661
;
662
; SOCKET_accept
663
;
664
;  IN:  socket number in ecx
665
;       addr in edx
666
;       addrlen in esi
667
;  OUT: eax is socket num, -1 on error
668
;
669
;-----------------------------------------------------------------
670
align 4
671
SOCKET_accept:
672
 
3556 hidnplayr 673
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 674
 
675
        call    SOCKET_num_to_ptr
676
        jz      s_error
677
 
678
        test    [eax + SOCKET.options], SO_ACCEPTCON
679
        jz      s_error
680
 
681
        cmp     [eax + SOCKET.Domain], AF_INET4
682
        jne     s_error
683
 
684
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
685
        jne     s_error
686
 
687
  .loop:
688
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
689
 
690
; Ok, we got a socket ptr
691
        mov     eax, [esi]
692
 
693
; Change thread ID to that of the current thread
694
        mov     ebx, [TASK_BASE]
695
        mov     ebx, [ebx + TASKDATA.pid]
696
        mov     [eax + SOCKET.TID], ebx
697
 
698
; Convert it to a socket number
699
        call    SOCKET_ptr_to_num
700
        jz      s_error
701
; and return it to caller
702
        mov     [esp+32], eax
703
        ret
704
 
705
  .block:
706
        test    [eax + SOCKET.options], SO_NONBLOCK
707
        jnz     s_error
708
 
709
        call    SOCKET_block
710
        jmp     .loop
711
 
712
;-----------------------------------------------------------------
713
;
714
; SOCKET_close
715
;
716
;  IN:  socket number in ecx
717
;  OUT: eax is socket num, -1 on error
718
;
719
;-----------------------------------------------------------------
720
align 4
721
SOCKET_close:
722
 
3556 hidnplayr 723
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 724
 
725
        call    SOCKET_num_to_ptr
726
        jz      s_error
727
 
728
        mov     dword [esp+32], 0                               ; The socket exists, so we will succeed in closing it.
729
 
730
  .socket:
731
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
732
 
733
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
734
        jz      @f
735
        call    SOCKET_notify.unblock                           ; Unblock it.
736
  @@:
737
 
738
        cmp     [eax + SOCKET.Domain], AF_INET4
739
        jne     .free
740
 
741
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
742
        je      .tcp
743
 
744
  .free:
745
        call    SOCKET_free
746
        ret
747
 
748
  .tcp:
749
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
750
        jb      .free
751
 
752
        call    TCP_usrclosed
753
        call    TCP_output      ;;;; Fixme: is this nescessary??
754
 
755
        ret
756
 
757
 
758
;-----------------------------------------------------------------
759
;
760
; SOCKET_receive
761
;
762
;  IN:  socket number in ecx
763
;       addr to buffer in edx
764
;       length of buffer in esi
765
;       flags in edi
766
;  OUT: eax is number of bytes copied, -1 on error
767
;
768
;-----------------------------------------------------------------
769
align 4
770
SOCKET_receive:
771
 
3556 hidnplayr 772
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 773
 
774
        call    SOCKET_num_to_ptr
775
        jz      s_error
776
 
3565 hidnplayr 777
        call    [eax + SOCKET.rcv_proc]
3545 hidnplayr 778
 
3565 hidnplayr 779
        mov     [esp+32], eax
780
        ret
3545 hidnplayr 781
 
3565 hidnplayr 782
 
3545 hidnplayr 783
align 4
784
SOCKET_receive_dgram:
785
 
3556 hidnplayr 786
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 787
 
788
        mov     ebx, esi
789
        mov     edi, edx                                        ; addr to buffer
790
 
791
  .loop:
792
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block      ; destroys esi and ecx
793
 
794
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 795
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 796
 
797
        cmp     ecx, ebx
798
        ja      .too_small
799
 
3565 hidnplayr 800
        push    ecx
3545 hidnplayr 801
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
802
        mov     esi, [esi + socket_queue_entry.data_ptr]
3556 hidnplayr 803
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 804
 
805
; copy the data
806
        shr     ecx, 1
807
        jnc     .nb
808
        movsb
809
  .nb:
810
        shr     ecx, 1
811
        jnc     .nw
812
        movsw
813
  .nw:
814
        test    ecx, ecx
815
        jz      .nd
816
        rep     movsd
817
  .nd:
818
 
819
        call    kernel_free                                     ; remove the packet
3565 hidnplayr 820
        pop     eax
821
 
3545 hidnplayr 822
        ret
823
 
824
  .too_small:
825
 
3556 hidnplayr 826
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n"
3565 hidnplayr 827
  .fail:
828
        mov     eax, -1
829
        ret
3545 hidnplayr 830
 
831
  .block:
832
        test    [eax + SOCKET.options], SO_NONBLOCK
3565 hidnplayr 833
        jnz     .fail
3545 hidnplayr 834
 
835
        call    SOCKET_block
836
        jmp     .loop
837
 
838
 
839
align 4
840
SOCKET_receive_local:
841
 
842
        ; does this socket have a PID yet?
843
        cmp     [eax + SOCKET.PID], 0
844
        jne     @f
845
 
846
        ; Change PID to that of current process
847
        mov     ebx, [TASK_BASE]
848
        mov     ebx, [ebx + TASKDATA.pid]
849
        mov     [eax + SOCKET.PID], ebx
850
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
851
      @@:
852
 
853
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
854
 
855
align 4
856
SOCKET_receive_stream:
857
 
3556 hidnplayr 858
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 859
 
860
        mov     ebx, edi
861
        mov     ecx, esi
862
        mov     edi, edx
863
        xor     edx, edx
864
 
865
        test    ebx, MSG_DONTWAIT
866
        jnz     .dontwait
867
  .loop:
868
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
869
        je      .block
870
  .dontwait:
871
        test    ebx, MSG_PEEK
872
        jnz     .peek
873
 
874
        add     eax, STREAM_SOCKET.rcv
875
        call    SOCKET_ring_read
876
        call    SOCKET_ring_free
877
 
3565 hidnplayr 878
        mov     eax, ecx                ; return number of bytes copied
3545 hidnplayr 879
        ret
880
 
881
  .peek:
3565 hidnplayr 882
        mov     eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3545 hidnplayr 883
        ret
884
 
885
  .block:
886
        test    [eax + SOCKET.options], SO_NONBLOCK
887
        jnz     .return0
888
 
889
        call    SOCKET_block
890
        jmp     .loop
891
 
892
  .return0:
3565 hidnplayr 893
        test    [eax + SOCKET.options], SS_CANTRCVMORE
894
        jz      .ok
895
 
896
        xor     eax, eax
897
        dec     eax
3545 hidnplayr 898
        ret
899
 
3565 hidnplayr 900
  .ok:
901
        xor     eax, eax
902
        ret
3545 hidnplayr 903
 
3565 hidnplayr 904
 
3545 hidnplayr 905
;-----------------------------------------------------------------
906
;
907
; SOCKET_send
908
;
909
;
910
;  IN:  socket number in ecx
911
;       pointer to data in edx
912
;       datalength in esi
913
;       flags in edi
914
;  OUT: -1 on error
915
;
916
;-----------------------------------------------------------------
917
align 4
918
SOCKET_send:
919
 
3556 hidnplayr 920
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 921
 
922
        call    SOCKET_num_to_ptr
923
        jz      s_error
924
 
925
        mov     ecx, esi
926
        mov     esi, edx
927
 
928
        jmp     [eax + SOCKET.snd_proc]
929
 
930
 
931
align 4
932
SOCKET_send_udp:
933
 
3556 hidnplayr 934
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 935
 
936
        mov     [esp+32], ecx
937
        call    UDP_output
938
        cmp     eax, -1
939
        je      s_error
940
        ret
941
 
942
 
943
align 4
944
SOCKET_send_tcp:
945
 
3556 hidnplayr 946
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 947
 
948
        push    eax
949
        add     eax, STREAM_SOCKET.snd
950
        call    SOCKET_ring_write
951
        pop     eax
952
 
953
        mov     [esp+32], ecx
954
 
955
        call    TCP_output
956
        ret
957
 
958
 
959
align 4
960
SOCKET_send_ip:
961
 
3556 hidnplayr 962
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 963
 
964
        mov     [esp+32], ecx
965
        call    IPv4_output_raw
966
        cmp     eax, -1
967
        je      s_error
968
        ret
969
 
970
 
971
align 4
972
SOCKET_send_icmp:
973
 
3556 hidnplayr 974
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 975
 
976
        mov     [esp+32], ecx
977
        call    ICMP_output_raw
978
        cmp     eax, -1
979
        je      s_error
980
        ret
981
 
982
 
983
align 4
984
SOCKET_send_pppoe:
985
 
3556 hidnplayr 986
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 987
 
988
        mov     [esp+32], ecx
989
        mov     ebx, [eax + SOCKET.device]
990
 
991
        call    PPPoE_discovery_output
992
        cmp     eax, -1
993
        je      s_error
994
        ret
995
 
996
 
997
 
998
align 4
999
SOCKET_send_local:
1000
 
1001
        ; does this socket have a PID yet?
1002
        cmp     [eax + SOCKET.PID], 0
1003
        jne     @f
1004
 
1005
        ; Change PID to that of current process
1006
        mov     ebx, [TASK_BASE]
1007
        mov     ebx, [ebx + TASKDATA.pid]
1008
        mov     [eax + SOCKET.PID], ebx
1009
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1010
      @@:
1011
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
1012
 
1013
align 4
1014
SOCKET_send_local_:
1015
 
3556 hidnplayr 1016
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1017
 
1018
        ; get the other side's socket and check if it still exists
1019
        mov     eax, [eax + SOCKET.device]
1020
        call    SOCKET_check
1021
        jz      s_error
1022
 
1023
        ; allright, shove in the data!
1024
        push    eax
1025
        add     eax, STREAM_SOCKET.rcv
1026
        call    SOCKET_ring_write
1027
        pop     eax
1028
 
1029
        ; return the number of written bytes (or errorcode) to application
1030
        mov     [esp+32], ecx
1031
 
1032
        ; and notify the other end
1033
        call    SOCKET_notify
1034
 
1035
        ret
1036
 
1037
 
1038
;-----------------------------------------------------------------
1039
;
1040
; SOCKET_get_options
1041
;
1042
;  IN:  ecx = socket number
1043
;       edx = pointer to the options:
1044
;               dd      level, optname, optval, optlen
1045
;  OUT: -1 on error
1046
;
1047
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1048
; TODO: find best way to notify that send()'ed data were acknowledged
1049
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1050
;
1051
;-----------------------------------------------------------------
1052
align 4
1053
SOCKET_get_opt:
1054
 
3556 hidnplayr 1055
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1056
 
1057
        call    SOCKET_num_to_ptr
1058
        jz      s_error
1059
 
1060
        cmp     dword [edx], IP_PROTO_TCP
1061
        jne     s_error
1062
        cmp     dword [edx+4], -2
1063
        je      @f
1064
        cmp     dword [edx+4], -3
1065
        jne     s_error
1066
@@:
1067
;        mov     eax, [edx+12]
1068
;        test    eax, eax
1069
;        jz      .fail
1070
;        cmp     dword [eax], 4
1071
;        mov     dword [eax], 4
1072
;        jb      .fail
1073
;        stdcall net_socket_num_to_addr, ecx
1074
;        test    eax, eax
1075
;        jz      .fail
1076
;        ; todo: check that eax is really TCP socket
1077
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1078
;        cmp     dword [edx+4], -2
1079
;        jz      @f
1080
;        mov     ecx, [eax + TCP_SOCKET.state]
1081
@@:
1082
        mov     eax, [edx+8]
1083
        test    eax, eax
1084
        jz      @f
1085
        mov     [eax], ecx
1086
@@:
1087
        mov     dword [esp+32], 0
1088
        ret
1089
 
1090
 
1091
 
1092
;-----------------------------------------------------------------
1093
;
1094
; SOCKET_set_options
1095
;
1096
;  IN:  ecx = socket number
1097
;       edx = pointer to the options:
1098
;               dd      level, optname, optlen, optval
1099
;  OUT: -1 on error
1100
;
1101
;-----------------------------------------------------------------
1102
align 4
1103
SOCKET_set_opt:
1104
 
3556 hidnplayr 1105
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1106
 
1107
        call    SOCKET_num_to_ptr
1108
        jz      s_error
1109
 
1110
        cmp     dword [edx], SOL_SOCKET
1111
        jne     s_error
1112
 
1113
        cmp     dword [edx+4], SO_BINDTODEVICE
1114
        je      .bind
1115
 
1116
        cmp     dword [edx+4], SO_BLOCK
1117
        je      .block
1118
 
1119
        jmp     s_error
1120
 
1121
  .bind:
1122
        cmp     dword [edx+8], 0
1123
        je      .unbind
1124
 
1125
        movzx   edx, byte [edx + 9]
3600 hidnplayr 1126
        cmp     edx, NET_DEVICES_MAX
3545 hidnplayr 1127
        ja      s_error
1128
 
1129
        mov     edx, [NET_DRV_LIST + 4*edx]
1130
        test    edx, edx
1131
        jz      s_error
1132
        mov     [eax + SOCKET.device], edx
1133
 
3556 hidnplayr 1134
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
3545 hidnplayr 1135
 
1136
        mov     dword [esp+32], 0       ; success!
1137
        ret
1138
 
1139
  .unbind:
1140
        mov     [eax + SOCKET.device], 0
1141
 
1142
        mov     dword [esp+32], 0       ; success!
1143
        ret
1144
 
1145
  .block:
1146
        cmp     dword [edx+8], 0
1147
        je      .unblock
1148
 
1149
        and     [eax + SOCKET.options], not SO_NONBLOCK
1150
 
1151
        mov     dword [esp+32], 0       ; success!
1152
        ret
1153
 
1154
  .unblock:
1155
        or      [eax + SOCKET.options], SO_NONBLOCK
1156
 
1157
        mov     dword [esp+32], 0       ; success!
1158
        ret
1159
 
1160
 
1161
 
1162
;-----------------------------------------------------------------
1163
;
1164
; SOCKET_pair
1165
;
1166
; Allocates a pair of linked LOCAL domain sockets
1167
;
1168
; IN: /
1169
; OUT: eax is socket1 num, -1 on error
1170
;      ebx is socket2 num
1171
;
1172
;-----------------------------------------------------------------
1173
align 4
1174
SOCKET_pair:
1175
 
3556 hidnplayr 1176
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1177
 
1178
        call    SOCKET_alloc
1179
        jz      s_error
1180
        mov     [esp+32], edi   ; application's eax
1181
 
1182
        mov     [eax + SOCKET.Domain], AF_LOCAL
1183
        mov     [eax + SOCKET.Type], SOCK_STREAM
1184
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1185
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1186
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1187
        mov     [eax + SOCKET.PID], 0
1188
        mov     ebx, eax
1189
 
1190
        call    SOCKET_alloc
1191
        jz      .error
1192
        mov     [esp+24], edi   ; application's ebx
1193
 
1194
        mov     [eax + SOCKET.Domain], AF_LOCAL
1195
        mov     [eax + SOCKET.Type], SOCK_STREAM
1196
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1197
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1198
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1199
        mov     [eax + SOCKET.PID], 0
1200
 
1201
        ; Link the two sockets to eachother
1202
        mov     [eax + SOCKET.device], ebx
1203
        mov     [ebx + SOCKET.device], eax
1204
 
1205
        lea     eax, [eax + STREAM_SOCKET.rcv]
1206
        call    SOCKET_ring_create
1207
 
1208
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1209
        call    SOCKET_ring_create
1210
        pop     eax
1211
 
1212
        ret
1213
 
1214
  .error:
1215
        mov     eax, ebx
1216
        call    SOCKET_free
1217
        jmp     s_error
1218
 
1219
 
1220
 
1221
;-----------------------------------------------------------------
1222
;
1223
; SOCKET_debug
1224
;
1225
;  Copies socket variables to application buffer
1226
;
1227
;  IN:  ecx = socket number
1228
;       edx = pointer to buffer
1229
;
1230
;  OUT: -1 on error
1231
;-----------------------------------------------------------------
1232
align 4
1233
SOCKET_debug:
1234
 
3556 hidnplayr 1235
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1236
 
1237
        mov     edi, edx
1238
 
1239
        test    ecx, ecx
1240
        jz      .returnall
1241
 
1242
        call    SOCKET_num_to_ptr
1243
        jz      s_error
1244
 
1245
        mov     esi, eax
1246
        mov     ecx, SOCKETBUFFSIZE/4
1247
        rep     movsd
1248
 
1249
        mov     dword [esp+32], 0
1250
        ret
1251
 
1252
  .returnall:
1253
        mov     ebx, net_sockets
1254
  .next_socket:
1255
        mov     ebx, [ebx + SOCKET.NextPtr]
1256
        test    ebx, ebx
1257
        jz      .done
1258
        mov     eax, [ebx + SOCKET.Number]
1259
        stosd
1260
        jmp     .next_socket
1261
  .done:
1262
        xor     eax, eax
1263
        stosd
1264
 
1265
        mov     dword [esp+32], 0
1266
        ret
1267
 
1268
 
1269
;-----------------------------------------------------------------
1270
;
1271
; SOCKET_find_port
1272
;
1273
; Fills in the local port number for TCP and UDP sockets
1274
; This procedure always works because the number of sockets is
1275
; limited to a smaller number then the number of possible ports
1276
;
1277
;  IN:  eax = socket pointer
1278
;  OUT: /
1279
;
1280
;-----------------------------------------------------------------
1281
align 4
1282
SOCKET_find_port:
1283
 
3556 hidnplayr 1284
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1285
 
1286
        push    ebx esi ecx
1287
 
1288
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1289
        je      .udp
1290
 
1291
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1292
        je      .tcp
1293
 
1294
        pop     ecx esi ebx
1295
        ret
1296
 
1297
  .udp:
1298
        mov     bx, [last_UDP_port]
1299
        call    .findit
1300
        mov     [last_UDP_port], bx
1301
 
1302
        pop     ecx esi ebx
1303
        ret
1304
 
1305
  .tcp:
1306
        mov     bx, [last_TCP_port]
1307
        call    .findit
1308
        mov     [last_TCP_port], bx
1309
 
1310
        pop     ecx esi ebx
1311
        ret
1312
 
1313
 
1314
  .restart:
1315
        mov     bx, MIN_EPHEMERAL_PORT_N
1316
  .findit:
1317
        cmp     bx, MAX_EPHEMERAL_PORT_N
1318
        je      .restart
1319
 
1320
        add     bh, 1
1321
        adc     bl, 0
1322
 
1323
        call    SOCKET_check_port
1324
        jz      .findit
1325
        ret
1326
 
1327
 
1328
 
1329
;-----------------------------------------------------------------
1330
;
1331
; SOCKET_check_port (to be used with AF_INET only!)
1332
;
1333
; Checks if a local port number is unused
1334
; If the proposed port number is unused, it is filled in in the socket structure
1335
;
1336
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1337
;        bx = proposed socket number (network byte order)
1338
;
1339
;  OUT:  ZF = set on error
1340
;
1341
;-----------------------------------------------------------------
1342
align 4
1343
SOCKET_check_port:
1344
 
3556 hidnplayr 1345
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1346
 
1347
        mov     ecx, [eax + SOCKET.Protocol]
1348
        mov     edx, [eax + IP_SOCKET.LocalIP]
1349
        mov     esi, net_sockets
1350
 
1351
  .next_socket:
1352
        mov     esi, [esi + SOCKET.NextPtr]
1353
        or      esi, esi
1354
        jz      .port_ok
1355
 
1356
        cmp     [esi + SOCKET.Protocol], ecx
1357
        jne     .next_socket
1358
 
1359
        cmp     [esi + IP_SOCKET.LocalIP], edx
1360
        jne     .next_socket
1361
 
1362
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1363
        jne     .next_socket
1364
 
3556 hidnplayr 1365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1366
        ret
1367
 
1368
  .port_ok:
3556 hidnplayr 1369
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1370
        mov     [eax + UDP_SOCKET.LocalPort], bx
1371
        or      bx, bx                                  ; clear the zero-flag
1372
        ret
1373
 
1374
 
1375
 
1376
;-----------------------------------------------------------------
1377
;
1378
; SOCKET_input
1379
;
1380
; Updates a (stateless) socket with received data
1381
;
1382
; Note: the mutex should already be set !
1383
;
1384
;  IN:  eax = socket ptr
1385
;       ecx = data size
1386
;       esi = ptr to data
1387
;       [esp] = ptr to buf
1388
;       [esp + 4] = buf size
1389
;
1390
;  OUT: /
1391
;
1392
;-----------------------------------------------------------------
1393
align 4
1394
SOCKET_input:
1395
 
3556 hidnplayr 1396
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1397
 
1398
        mov     [esp+4], ecx
1399
        push    esi
1400
        mov     esi, esp
1401
 
1402
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1403
 
3556 hidnplayr 1404
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1405
        add     esp, sizeof.socket_queue_entry
1406
 
1407
        pusha
1408
        lea     ecx, [eax + SOCKET.mutex]
1409
        call    mutex_unlock
1410
        popa
1411
 
1412
        jmp     SOCKET_notify
1413
 
1414
  .full:
3556 hidnplayr 1415
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1416
 
1417
        pusha
1418
        lea     ecx, [eax + SOCKET.mutex]
1419
        call    mutex_unlock
1420
        popa
1421
 
1422
        call    kernel_free
1423
        add     esp, 8
1424
 
1425
        ret
1426
 
1427
 
1428
;--------------------------
1429
;
1430
; eax = ptr to ring struct (just a buffer of the right size)
1431
;
1432
align 4
1433
SOCKET_ring_create:
1434
 
1435
        push    esi
1436
        mov     esi, eax
1437
 
1438
        push    edx
1439
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1440
        pop     edx
1441
 
3556 hidnplayr 1442
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
3545 hidnplayr 1443
 
1444
        pusha
1445
        lea     ecx, [esi + RING_BUFFER.mutex]
1446
        call    mutex_init
1447
        popa
1448
 
1449
        mov     [esi + RING_BUFFER.start_ptr], eax
1450
        mov     [esi + RING_BUFFER.write_ptr], eax
1451
        mov     [esi + RING_BUFFER.read_ptr], eax
1452
        mov     [esi + RING_BUFFER.size], 0
1453
        add     eax, SOCKET_MAXDATA
1454
        mov     [esi + RING_BUFFER.end_ptr], eax
1455
        mov     eax, esi
1456
        pop     esi
1457
 
1458
        ret
1459
 
1460
;-----------------------------------------------------------------
1461
;
1462
; SOCKET_ring_write
1463
;
1464
; Adds data to a stream socket, and updates write pointer and size
1465
;
1466
;  IN:  eax = ptr to ring struct
1467
;       ecx = data size
1468
;       esi = ptr to data
1469
;
1470
;  OUT: ecx = number of bytes stored
1471
;
1472
;-----------------------------------------------------------------
1473
align 4
1474
SOCKET_ring_write:
1475
 
3556 hidnplayr 1476
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1477
 
1478
; lock mutex
1479
        pusha
1480
        lea     ecx, [eax + RING_BUFFER.mutex]
1481
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1482
        popa
1483
 
1484
; calculate available size
1485
        mov     edi, SOCKET_MAXDATA
1486
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1487
        cmp     ecx, edi
1488
        jbe     .copy
1489
        mov     ecx, edi
1490
  .copy:
1491
        mov     edi, [eax + RING_BUFFER.write_ptr]
3556 hidnplayr 1492
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1493
 
1494
; update write ptr
1495
        push    edi
1496
        add     edi, ecx
1497
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1498
        jb      @f
1499
        sub     edi, SOCKET_MAXDATA                             ; WRAP
1500
  @@:
1501
        mov     [eax + RING_BUFFER.write_ptr], edi
1502
        pop     edi
1503
 
1504
; update size
1505
        add     [eax + RING_BUFFER.size], ecx
1506
 
1507
; copy the data
1508
        push    ecx
1509
        shr     ecx, 1
1510
        jnc     .nb
1511
        movsb
1512
  .nb:
1513
        shr     ecx, 1
1514
        jnc     .nw
1515
        movsw
1516
  .nw:
1517
        test    ecx, ecx
1518
        jz      .nd
1519
        rep     movsd
1520
  .nd:
1521
        pop     ecx
1522
 
1523
; unlock mutex
1524
        push    eax ecx
1525
        lea     ecx, [eax + RING_BUFFER.mutex]
1526
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1527
        pop     ecx eax
1528
 
1529
        ret
1530
 
1531
;-----------------------------------------------------------------
1532
;
1533
; SOCKET_ring_read
1534
;
1535
;  IN:  eax = ring struct ptr
1536
;       ecx = bytes to read
1537
;       edx = offset
1538
;       edi = ptr to buffer start
1539
;
1540
;  OUT: eax = unchanged
1541
;       ecx = number of bytes read (0 on error)
1542
;       edx = destroyed
1543
;       esi = destroyed
1544
;       edi = ptr to buffer end
1545
;
1546
;-----------------------------------------------------------------
1547
align 4
1548
SOCKET_ring_read:
1549
 
3556 hidnplayr 1550
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1551
 
1552
        pusha
1553
        lea     ecx, [eax + RING_BUFFER.mutex]
1554
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1555
        popa
1556
 
1557
        mov     esi, [eax + RING_BUFFER.read_ptr]
1558
        add     esi, edx                                        ; esi = start_ptr + offset
1559
 
1560
        neg     edx
1561
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1562
        jle     .no_data_at_all
1563
 
1564
        pusha
1565
        lea     ecx, [eax + RING_BUFFER.mutex]
1566
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1567
        popa
1568
 
1569
        cmp     ecx, edx
1570
        ja      .less_data
1571
 
1572
  .copy:
3556 hidnplayr 1573
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1574
        push    ecx
1575
        shr     ecx, 1
1576
        jnc     .nb
1577
        movsb
1578
  .nb:
1579
        shr     ecx, 1
1580
        jnc     .nw
1581
        movsw
1582
  .nw:
1583
        test    ecx, ecx
1584
        jz      .nd
1585
        rep     movsd
1586
  .nd:
1587
        pop     ecx
1588
        ret
1589
 
1590
  .no_data_at_all:
1591
        pusha
1592
        lea     ecx, [eax + RING_BUFFER.mutex]
1593
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1594
        popa
1595
 
3556 hidnplayr 1596
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1597
        xor     ecx, ecx
1598
        ret
1599
 
1600
  .less_data:
1601
        mov     ecx, edx
1602
        jmp     .copy
1603
 
1604
 
1605
;-----------------------------------------------------------------
1606
;
1607
; SOCKET_ring_free
1608
;
1609
; Free's some bytes from the ringbuffer
1610
;
1611
;  IN:  eax = ptr to ring struct
1612
;       ecx = data size
1613
;
1614
;  OUT: ecx = number of bytes free-ed
1615
;
1616
;-----------------------------------------------------------------
1617
align 4
1618
SOCKET_ring_free:
1619
 
3556 hidnplayr 1620
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1621
 
1622
        push    eax ecx
1623
        lea     ecx, [eax + RING_BUFFER.mutex]
1624
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1625
        pop     ecx eax
1626
 
1627
        sub     [eax + RING_BUFFER.size], ecx
1628
        jb      .error
1629
        add     [eax + RING_BUFFER.read_ptr], ecx
1630
 
1631
        mov     edx, [eax + RING_BUFFER.end_ptr]
1632
        cmp     [eax + RING_BUFFER.read_ptr], edx
1633
        jb      @f
1634
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1635
       @@:
1636
 
1637
        push    eax ecx
1638
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1639
        call    mutex_unlock
1640
        pop     ecx eax
1641
 
1642
        ret
1643
 
1644
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3556 hidnplayr 1645
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1646
        add     [eax + RING_BUFFER.size], ecx
1647
 
1648
        push    eax
1649
        lea     ecx, [eax + RING_BUFFER.mutex]
1650
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1651
        pop     eax
1652
 
1653
        xor     ecx, ecx
1654
        ret
1655
 
1656
 
1657
;-----------------------------------------------------------------
1658
;
1659
; SOCKET_block
1660
;
1661
; Suspends the thread attached to a socket
1662
;
1663
;  IN:  eax = socket ptr
1664
;  OUT: /
1665
;
1666
;-----------------------------------------------------------------
1667
align 4
1668
SOCKET_block:
1669
 
3556 hidnplayr 1670
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1671
 
1672
        pushf
1673
        cli
1674
 
1675
        ; Set the 'socket is blocked' flag
1676
        or      [eax + SOCKET.state], SS_BLOCKED
1677
 
1678
        ; Suspend the thread
1679
        push    edx
1680
        mov     edx, [TASK_BASE]
1681
        mov     [edx + TASKDATA.state], 1               ; Suspended
1682
 
1683
        ; Remember the thread ID so we can wake it up again
1684
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1685
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1686
        mov     [eax + SOCKET.TID], edx
1687
        pop     edx
1688
 
1689
        call    change_task
1690
        popf
1691
 
3556 hidnplayr 1692
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
3545 hidnplayr 1693
 
1694
        ret
1695
 
1696
 
1697
;-----------------------------------------------------------------
1698
;
1699
; SOCKET_notify
1700
;
1701
; notify's the owner of a socket that something happened
1702
;
1703
;  IN:  eax = socket ptr
1704
;  OUT: /
1705
;
1706
;-----------------------------------------------------------------
1707
align 4
1708
SOCKET_notify:
1709
 
3556 hidnplayr 1710
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1711
 
1712
        call    SOCKET_check
1713
        jz      .error
1714
 
1715
        test    [eax + SOCKET.state], SS_BLOCKED
1716
        jnz     .unblock
1717
 
1718
        test    [eax + SOCKET.options], SO_NONBLOCK
1719
        jz      .error
1720
 
1721
        push    eax ecx esi
1722
 
1723
; socket exists and is of non blocking type.
1724
; We'll try to flag an event to the thread
1725
 
1726
        mov     eax, [eax + SOCKET.TID]
1727
        test    eax, eax
1728
        jz      .done
1729
        mov     ecx, 1
1730
        mov     esi, TASK_DATA + TASKDATA.pid
1731
 
1732
  .next_pid:
1733
        cmp     [esi], eax
1734
        je      .found_pid
1735
        inc     ecx
1736
        add     esi, 0x20
1737
        cmp     ecx, [TASK_COUNT]
1738
        jbe     .next_pid
1739
; PID not found, TODO: close socket!
1740
        jmp     .done
1741
 
1742
  .found_pid:
1743
        shl     ecx, 8
1744
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1745
 
3556 hidnplayr 1746
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
3545 hidnplayr 1747
 
1748
        jmp     .done
1749
 
1750
  .unblock:
1751
        push    eax ecx esi
1752
        ; Clear the 'socket is blocked' flag
1753
        and     [eax + SOCKET.state], not SS_BLOCKED
1754
 
1755
        ; Find the thread's TASK_DATA
1756
        mov     eax, [eax + SOCKET.TID]
1757
        test    eax, eax
1758
        jz      .error
1759
        xor     ecx, ecx
1760
        inc     ecx
1761
        mov     esi, TASK_DATA
1762
  .next:
1763
        cmp     [esi + TASKDATA.pid], eax
1764
        je      .found
1765
        inc     ecx
1766
        add     esi, 0x20
1767
        cmp     ecx, [TASK_COUNT]
1768
        jbe     .next
1769
        jmp     .error
1770
  .found:
1771
 
1772
        ; Run the thread
1773
        mov     [esi + TASKDATA.state], 0       ; Running
3556 hidnplayr 1774
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
3545 hidnplayr 1775
 
1776
  .done:
1777
        pop     esi ecx eax
1778
 
1779
  .error:
1780
        ret
1781
 
1782
 
1783
;--------------------------------------------------------------------
1784
;
1785
; SOCKET_alloc
1786
;
1787
; Allocate memory for socket data and put new socket into the list
1788
; Newly created socket is initialized with calling PID and number and
1789
; put into beginning of list (which is a fastest way).
1790
;
1791
; IN:  /
1792
; OUT: eax = 0 on error, socket ptr otherwise
1793
;      edi = socket number
1794
;       ZF = cleared on error
1795
;
1796
;--------------------------------------------------------------------
1797
align 4
1798
SOCKET_alloc:
1799
 
1800
        push    ebx
1801
 
1802
        stdcall kernel_alloc, SOCKETBUFFSIZE
3556 hidnplayr 1803
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1804
        or      eax, eax
1805
        jz      .exit
1806
 
1807
; zero-initialize allocated memory
1808
        push    eax
1809
        mov     edi, eax
1810
        mov     ecx, SOCKETBUFFSIZE / 4
1811
        xor     eax, eax
1812
        rep     stosd
1813
        pop     eax
1814
 
1815
; set send-and receive procedures to return -1
1816
        mov     [eax + SOCKET.snd_proc], s_error
1817
        mov     [eax + SOCKET.rcv_proc], s_error
1818
 
1819
; find first free socket number and use it
1820
        mov     edi, [last_socket_num]
1821
  .next_socket_number:
1822
        inc     edi
1823
        jz      .next_socket_number     ; avoid socket nr 0
1824
        cmp     edi, -1
1825
        je      .next_socket_number     ; avoid socket nr -1
1826
        mov     ebx, net_sockets
1827
  .next_socket:
1828
        mov     ebx, [ebx + SOCKET.NextPtr]
1829
        test    ebx, ebx
1830
        jz      .last_socket
1831
 
1832
        cmp     [ebx + SOCKET.Number], edi
1833
        jne     .next_socket
1834
        jmp     .next_socket_number
1835
 
1836
  .last_socket:
1837
        mov     [last_socket_num], edi
1838
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 1839
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 1840
 
1841
; Fill in PID
1842
        mov     ebx, [TASK_BASE]
1843
        mov     ebx, [ebx + TASKDATA.pid]
1844
        mov     [eax + SOCKET.PID], ebx
1845
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1846
 
1847
; init mutex
1848
        pusha
1849
        lea     ecx, [eax + SOCKET.mutex]
1850
        call    mutex_init
1851
        popa
1852
 
1853
; add socket to the list by re-arranging some pointers
1854
        mov     ebx, [net_sockets + SOCKET.NextPtr]
1855
 
1856
        mov     [eax + SOCKET.PrevPtr], net_sockets
1857
        mov     [eax + SOCKET.NextPtr], ebx
1858
 
1859
        test    ebx, ebx
1860
        jz      @f
1861
 
1862
        pusha
1863
        lea     ecx, [ebx + SOCKET.mutex]
1864
        call    mutex_lock
1865
        popa
1866
 
1867
        mov     [ebx + SOCKET.PrevPtr], eax
1868
 
1869
        pusha
1870
        lea     ecx, [ebx + SOCKET.mutex]
1871
        call    mutex_unlock
1872
        popa
1873
       @@:
1874
 
1875
        mov     [net_sockets + SOCKET.NextPtr], eax
1876
        or      eax, eax                ; used to clear zero flag
1877
  .exit:
1878
        pop     ebx
1879
 
1880
        ret
1881
 
1882
 
1883
;----------------------------------------------------
1884
;
1885
; SOCKET_free
1886
;
1887
; Free socket data memory and remove socket from the list
1888
;
1889
; IN:  eax = socket ptr
1890
; OUT: /
1891
;
1892
;----------------------------------------------------
1893
align 4
1894
SOCKET_free:
1895
 
3556 hidnplayr 1896
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 1897
 
1898
        call    SOCKET_check
1899
        jz      .error
1900
 
1901
        push    ebx
1902
 
1903
        pusha
1904
        lea     ecx, [eax + SOCKET.mutex]
1905
        call    mutex_lock
1906
        popa
1907
 
1908
        cmp     [eax + SOCKET.Domain], AF_INET4
1909
        jnz     .no_tcp
1910
 
1911
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1912
        jnz     .no_tcp
1913
 
1914
        mov     ebx, eax
1915
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
1916
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
1917
        mov     eax, ebx
1918
  .no_tcp:
1919
 
1920
        push    eax                             ; this will be passed to kernel_free
1921
        mov     ebx, [eax + SOCKET.NextPtr]
1922
        mov     eax, [eax + SOCKET.PrevPtr]
1923
 
3556 hidnplayr 1924
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 1925
 
1926
        test    eax, eax
1927
        jz      @f
1928
        mov     [eax + SOCKET.NextPtr], ebx
1929
       @@:
1930
 
1931
        test    ebx, ebx
1932
        jz      @f
1933
        mov     [ebx + SOCKET.PrevPtr], eax
1934
       @@:
1935
 
1936
        call    kernel_free
1937
        pop     ebx
1938
 
3556 hidnplayr 1939
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
3545 hidnplayr 1940
 
1941
  .error:
1942
        ret
1943
 
1944
;------------------------------------
1945
;
1946
; SOCKET_fork
1947
;
1948
; Create a child socket
1949
;
1950
; IN:  socket nr in ebx
1951
; OUT: child socket nr in eax
1952
;
1953
;-----------------------------------
1954
align 4
1955
SOCKET_fork:
1956
 
3556 hidnplayr 1957
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 1958
 
1959
; Exit if backlog queue is full
1960
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1961
        cmp     ax, [ebx + SOCKET.backlog]
1962
        jae     .fail
1963
 
1964
; Allocate new socket
1965
        push    ebx
1966
        call    SOCKET_alloc
1967
        pop     ebx
1968
        jz      .fail
1969
 
1970
        push    eax
1971
        mov     esi, esp
1972
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
1973
        pop     eax
1974
 
1975
; Copy structure from current socket to new
1976
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
1977
        lea     esi, [ebx + SOCKET.PID]
1978
        lea     edi, [eax + SOCKET.PID]
1979
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
1980
        rep     movsd
1981
 
1982
        and     [eax + SOCKET.options], not SO_ACCEPTCON
1983
 
1984
        ret
1985
 
1986
  .fail2:
1987
        add     esp, 4+4+4
1988
  .fail:
3556 hidnplayr 1989
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 1990
        xor     eax, eax
1991
        ret
1992
 
1993
 
1994
;---------------------------------------------------
1995
;
1996
; SOCKET_num_to_ptr
1997
;
1998
; Get socket structure address by its number
1999
;
2000
; IN:  ecx = socket number
2001
; OUT: eax = 0 on error, socket ptr otherwise
2002
;       ZF = set on error
2003
;
2004
;---------------------------------------------------
2005
align 4
2006
SOCKET_num_to_ptr:
2007
 
3556 hidnplayr 2008
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2009
 
2010
        mov     eax, net_sockets
2011
 
2012
  .next_socket:
2013
        mov     eax, [eax + SOCKET.NextPtr]
2014
        or      eax, eax
2015
        jz      .error
2016
        cmp     [eax + SOCKET.Number], ecx
2017
        jne     .next_socket
2018
 
2019
        test    eax, eax
2020
 
3556 hidnplayr 2021
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2022
        ret
2023
 
2024
  .error:
3556 hidnplayr 2025
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_nuto_ptr: not found\n", eax
3545 hidnplayr 2026
        ret
2027
 
2028
 
2029
;---------------------------------------------------
2030
;
2031
; SOCKET_ptr_to_num
2032
;
2033
; Get socket number by its address
2034
;
2035
; IN:  eax = socket ptr
2036
; OUT: eax = 0 on error, socket num otherwise
2037
;       ZF = set on error
2038
;
2039
;---------------------------------------------------
2040
align 4
2041
SOCKET_ptr_to_num:
2042
 
3556 hidnplayr 2043
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2044
 
2045
        call    SOCKET_check
2046
        jz      .error
2047
 
2048
        mov     eax, [eax + SOCKET.Number]
2049
 
3556 hidnplayr 2050
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2051
        ret
2052
 
2053
  .error:
3556 hidnplayr 2054
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2055
        ret
2056
 
2057
 
2058
;---------------------------------------------------
2059
;
2060
; SOCKET_check
2061
;
2062
; checks if the given value is really a socket ptr
2063
;
2064
; IN:  eax = socket ptr
2065
; OUT: eax = 0 on error, unchanged otherwise
2066
;       ZF = set on error
2067
;
2068
;---------------------------------------------------
2069
align 4
2070
SOCKET_check:
2071
 
3556 hidnplayr 2072
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2073
 
2074
        push    ebx
2075
        mov     ebx, net_sockets
2076
 
2077
  .next_socket:
2078
        mov     ebx, [ebx + SOCKET.NextPtr]
2079
        or      ebx, ebx
2080
        jz      .done
2081
        cmp     ebx, eax
2082
        jnz     .next_socket
2083
 
2084
  .done:
2085
        mov     eax, ebx
2086
        test    eax, eax
2087
        pop     ebx
2088
 
2089
        ret
2090
 
2091
 
2092
 
2093
;---------------------------------------------------
2094
;
2095
; SOCKET_check_owner
2096
;
2097
; checks if the caller application owns the socket
2098
;
2099
; IN:  eax = socket ptr
2100
; OUT:  ZF = true/false
2101
;
2102
;---------------------------------------------------
2103
align 4
2104
SOCKET_check_owner:
2105
 
3556 hidnplayr 2106
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2107
 
2108
        push    ebx
2109
        mov     ebx, [TASK_BASE]
2110
        mov     ebx, [ebx + TASKDATA.pid]
2111
        cmp     [eax + SOCKET.PID], ebx
2112
        pop      ebx
2113
 
2114
        ret
2115
 
2116
 
2117
 
2118
 
2119
;------------------------------------------------------
2120
;
2121
; SOCKET_process_end
2122
;
2123
; Kernel calls this function when a certain process ends
2124
; This function will check if the process had any open sockets
2125
; And update them accordingly
2126
;
2127
; IN:  edx = pid
2128
; OUT: /
2129
;
2130
;------------------------------------------------------
2131
align 4
2132
SOCKET_process_end:
2133
 
3556 hidnplayr 2134
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2135
 
2136
        push    ebx
2137
        mov     ebx, net_sockets
2138
 
2139
  .next_socket:
2140
        mov     ebx, [ebx + SOCKET.NextPtr]
2141
  .next_socket_test:
2142
        test    ebx, ebx
2143
        jz      .done
2144
 
2145
        cmp     [ebx + SOCKET.PID], edx
2146
        jne     .next_socket
2147
 
3556 hidnplayr 2148
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2149
 
2150
        mov     [ebx + SOCKET.PID], 0
2151
        mov     eax, ebx
2152
        mov     ebx, [ebx + SOCKET.NextPtr]
2153
        pusha
2154
        call    SOCKET_close.socket
2155
        popa
2156
        jmp     .next_socket_test
2157
 
2158
  .done:
2159
        pop     ebx
2160
 
2161
        ret
2162
 
2163
 
2164
 
2165
 
2166
;-----------------------------------------------------------------
2167
;
2168
; SOCKET_is_connecting
2169
;
2170
;  IN:  eax = socket ptr
2171
;  OUT: /
2172
;
2173
;-----------------------------------------------------------------
2174
 
2175
align 4
2176
SOCKET_is_connecting:
2177
 
3556 hidnplayr 2178
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2179
 
2180
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2181
        or      [eax + SOCKET.options], SS_ISCONNECTING
2182
 
2183
        jmp     SOCKET_notify
2184
 
2185
 
2186
 
2187
;-----------------------------------------------------------------
2188
;
2189
; SOCKET_is_connected
2190
;
2191
;  IN:  eax = socket ptr
2192
;  OUT: /
2193
;
2194
;-----------------------------------------------------------------
2195
 
2196
align 4
2197
SOCKET_is_connected:
2198
 
3556 hidnplayr 2199
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2200
 
2201
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2202
        or      [eax + SOCKET.options], SS_ISCONNECTED
2203
 
2204
        jmp     SOCKET_notify
2205
 
2206
 
2207
 
2208
 
2209
;-----------------------------------------------------------------
2210
;
2211
; SOCKET_is_disconnecting
2212
;
2213
;  IN:  eax = socket ptr
2214
;  OUT: /
2215
;
2216
;-----------------------------------------------------------------
2217
 
2218
align 4
2219
SOCKET_is_disconnecting:
2220
 
3556 hidnplayr 2221
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2222
 
2223
        and     [eax + SOCKET.options], not (SS_ISCONNECTING)
2224
        or      [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
2225
 
2226
        jmp     SOCKET_notify
2227
 
2228
 
2229
 
2230
;-----------------------------------------------------------------
2231
;
2232
; SOCKET_is_disconnected
2233
;
2234
;  IN:  eax = socket ptr
2235
;  OUT: /
2236
;
2237
;-----------------------------------------------------------------
2238
 
2239
align 4
2240
SOCKET_is_disconnected:
2241
 
3556 hidnplayr 2242
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2243
 
2244
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2245
        or      [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
2246
 
2247
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2248
        je      .tcp
2249
 
2250
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
2251
        je      .udp
2252
 
2253
        jmp     SOCKET_notify
2254
 
2255
  .tcp:
2256
  .udp:
2257
        mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
2258
        mov     [eax + UDP_SOCKET.RemotePort], 0
2259
 
2260
        jmp     SOCKET_notify
2261
 
2262
 
2263
;-----------------------------------------------------------------
2264
;
2265
; SOCKET_cant_recv_more
2266
;
2267
;  IN:  eax = socket ptr
2268
;  OUT: /
2269
;
2270
;-----------------------------------------------------------------
2271
 
2272
align 4
2273
SOCKET_cant_recv_more:
2274
 
3556 hidnplayr 2275
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2276
 
2277
        or      [eax + SOCKET.options], SS_CANTRCVMORE
2278
 
3565 hidnplayr 2279
        call    SOCKET_notify
2280
 
3545 hidnplayr 2281
        ret
2282
 
2283
 
2284
 
2285
;-----------------------------------------------------------------
2286
;
2287
; SOCKET_cant_send_more
2288
;
2289
;  IN:  eax = socket ptr
2290
;  OUT: /
2291
;
2292
;-----------------------------------------------------------------
2293
 
2294
align 4
2295
SOCKET_cant_send_more:
2296
 
3556 hidnplayr 2297
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2298
 
2299
        or      [eax + SOCKET.options], SS_CANTSENDMORE
3565 hidnplayr 2300
        mov     [eax + SOCKET.snd_proc], s_error
3545 hidnplayr 2301
 
3565 hidnplayr 2302
        call    SOCKET_notify
2303
 
3545 hidnplayr 2304
        ret