Subversion Repositories Kolibri OS

Rev

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