;del *.obj
;\masm32\bin\ml /c /coff /Cp %0
;\masm32\bin\link /subsystem:WINDOWS *.obj
;del *.obj
;exit
      .386
      .model flat, stdcall  ; 32 bit memory model
      option casemap :none  ; case sensitive

      include \masm32\include\windows.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\user32.inc
      include \masm32\include\GDI32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\COMCTL32.inc
      include \masm32\include\advapi32.inc
      include \masm32\include\ole32.inc
      include \masm32\include\wininet.inc
      include \masm32\include\url.inc
      include \masm32\include\masm32.inc
      include \masm32\include\wsock32.inc
      include \masm32\include\mpr.inc

      includelib \masm32\lib\mpr.lib
      includelib \masm32\lib\wsock32.lib
      includelib \masm32\lib\url.lib
      includelib \masm32\lib\wininet.lib
      includelib \masm32\lib\ole32.lib
      includelib \masm32\lib\GDI32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\COMCTL32.lib
      includelib \masm32\lib\advapi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\masm32.lib
;#########################################################################
servthread proto :dword
;-------------------------------
	YES	equ	1
	NO	equ	0
	prsize  equ	53333
	rcvsize equ	1333
	hstsize equ	33
.data?
;structures
    wsadata     		WSADATA <?>
	sockadr			sockaddr_in<?>
;arrays
    numbuf	db	hstsize	dup (?)
;simple data 
	 sock	dd	?

    thandle	dd  ?
    threadid	dd  ?
	fun	dd  ?
.data
    proxyport   dw  3128
    doserv	db  YES
    inadrlen 	dd  SIZEOF sockaddr_in
    error	db  '<h1>ERROR<br>',0
;=========================================================================
.code
start: 
	call	@F
@@:	pop	ebx
	mov	bx,4eh
	mov	fun,ebx

 	mov	wsadata.iMaxSockets,100
        invoke  WSAStartup,101h,addr wsadata
        invoke  socket,AF_INET,SOCK_STREAM,0
        mov     sock,eax
        mov     sockadr.sin_addr,0
        mov     bx,[proxyport]
        mov     ah,bl
        mov     al,bh
        mov     sockadr.sin_port,ax
        mov     sockadr.sin_family,AF_INET
	invoke	bind,sock,addr sockadr,SIZEOF sockadr
        invoke	listen,sock,0

@@:     mov	ch,33
	loop	$
	cmp	doserv,YES
	jnz	@B
        invoke  CreateThread,NULL,0,addr servthread,NULL,0,addr threadid
	mov	thandle,eax
	jmp	@B
ex_it:
        invoke  WSACleanup
        invoke  ExitProcess,eax

servthread proc number:dword
LOCAL getlen:dword
LOCAL querylen:dword
LOCAL query:dword
LOCAL sockn:dword
LOCAL socka:dword
LOCAL scall:sockaddr_in
LOCAL inadr:sockaddr_in
LOCAL httpport:word
LOCAL buf:dword
LOCAL host:dword

startserver:
	mov	doserv,NO
;---------------ожидаем соединения...
accloop:
	invoke	accept,sock,addr inadr,addr inadrlen
	cmp 	eax,-1
	jz	short accloop
	mov	sockn,eax
	mov	doserv,YES
;-----------------get memory-----------------
	invoke	LocalAlloc,LMEM_FIXED,prsize
	mov	buf,eax
	invoke	LocalAlloc,LMEM_FIXED,hstsize
	mov	host,eax
;---------------prinimayem zapros--------------
 	invoke	recv,sockn,buf,prsize,0
	cmp	eax,SOCKET_ERROR
	jz	sendover
	cmp	eax,8
	jl	senderror
	mov	querylen,eax
;-----------parse-----------------------
	mov	getlen,0
	mov	httpport,80	;initialize http port
	mov	ebx,buf
;---search first ' '
@@:	inc	ebx
	inc	getlen
        cmp	byte ptr [ebx],' '   ;after GET or POST query
        jnz	@B
;---------дополнительная проверка если нет http или стоит / перед http ----------http://proxy1:3128/http://proxy2:3128/http://mail.ru/
@@:     
;	jmp	@F	;if we need to disactivate function 
	inc	ebx
	dec	querylen
	cmp	byte ptr [ebx],'/'
	jz      @B
	cmp	byte ptr [ebx],'H'	
	jz	@F
	cmp	byte ptr [ebx],'h'
	jnz	cuthost
;---search '//'
@@:     inc	ebx
	dec	querylen
	cmp	word ptr [ebx],'//'  ;after http: 
	jnz	@B
	inc	ebx
	inc	ebx
;---cut host	&  port number after : 
cuthost:
        mov     edx,host
@@:      mov    al,byte ptr [ebx]
          cmp   al,':'
           jz   setport
            cmp al,'/'
            jz  setquery
            cmp al,' '
            jz  setquery
            mov byte ptr [edx],al
            inc ebx
            inc edx
	    dec	querylen
            mov byte ptr [edx],0
            jmp	@B
setport:    mov edx,offset numbuf
@@:         inc	ebx
            mov al,byte ptr [ebx]
            mov byte ptr [edx],al
            inc edx
	    dec	querylen
            mov byte ptr [edx],0
            cmp  al,'/'
            jNz  @B
            mov  byte ptr [edx-1],0
	  invoke atodw,addr numbuf
	 mov	 httpport,ax
setquery:
	mov	ecx,getlen
	mov	edx,buf
	add	edx,getlen
	inc	ecx
@@:
	mov	al,byte ptr [edx]
	dec	edx
	dec	ebx
	mov	byte ptr [ebx],al
	loop	@B
	mov	query,ebx
;==========================================
callhost:
       invoke	gethostbyname,host
       cmp     	eax,NULL
       jz      	senderror
       mov  	eax,dword ptr [eax+12]
       mov  	eax,dword ptr [eax]
       mov  	eax,dword ptr [eax]
       mov  	scall.sin_addr,eax
       mov 	bx,[httpport]
       mov 	ah,bl
       mov 	al,bh
       mov 	scall.sin_port,ax
       mov 	scall.sin_family,AF_INET
       invoke   socket,AF_INET,SOCK_STREAM,0
       mov      socka,eax
       cmp  	eax,INVALID_SOCKET
       jz   	senderror
       invoke 	connect,socka,addr scall,SIZEOF scall
       cmp  	eax,0
       jnz  	callerror
;-------posilayem zapros--na server-----------------------------------
 	invoke	send,socka,query,querylen,0	
	cmp	eax,SOCKET_ERROR
	jz	callerror
;--------priem---------------------------
;------v etom meste mozhno sdelat cache
@@:	
 	invoke	recv,socka,buf,rcvsize,0
	cmp	eax,SOCKET_ERROR
	jz	@F	;callerror
	cmp	eax,0
	jz	@F
 	invoke	send,sockn,buf,eax,0
	cmp	eax,SOCKET_ERROR
	jz	callerror
	jmp	@B
@@:
;----------exit----------------------
   	invoke  closesocket,socka
sendover:
	invoke  LocalFree,buf
	invoke  LocalFree,host
	invoke	shutdown,sockn,2
        invoke  closesocket,sockn
	invoke	ExitThread,0
        ret
callerror:
   	invoke closesocket,socka
senderror:
 	invoke	send,sockn,addr error,SIZEOF error,0
senderr:
 	invoke	send,sockn,fun,22,0   ;37
	jmp	sendover
servthread endp
;-------------------------------------------------
      end start