📄 umysqlvio.pas
字号:
exit;
end;
end
end;
if not haserr then
begin
ftype:=VIO_TYPE_SOCKET;
fsd:=sock;
fhPipe:=0;
result:=0;//no errors and we are connected (we can start talking to the server)
flast_error:='';
flast_errno:=0;
fastsend; //attempt to use fastsend
keepalive(TRUE);
exit;
end;
end;
{$ENDIF}
begin
//restore values if we cahnged them trying the pipe
host:=lhost;
unix_socket:=lunix_socket;
if (port=0)then
port:=mysql_port;
if (host='') then
host:='localhost';
sock := socket(AF_INET,SOCK_STREAM,0); //try grab a socket
if (sock = SOCKET_ERROR) then //error?
begin
flast_errno:=CR_IPSOCK_ERROR;
{$IFDEF _WIN_}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR],[WSAGetLastError]);
{$ELSE}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR],[errno]);
{$ENDIF}
result:=-8;//we failed the socket creation
exit;
end;
{$IFNDEF _WIN_}
ffcntl_mode := fcntl(fsd, F_GETFL);
{$ENDIF}
{$IFDEF _WIN_}
arg:=0;
ioctlsocket(fsd,FIONBIO,longint(arg));
{$ENDIF}
//try to resolve the host
fillchar(sock_addr,sizeof(sock_addr),#0);
sock_addr.sin_family := AF_INET;
ip_addr := inet_addr(pchar(host));
if (ip_addr <> INADDR_NONE) then
sock_addr.sin_addr:=in_addr(ip_addr)
else
begin
hp:=gethostbyname(pchar(host));
if (hp=nil) then
begin
flast_errno:=CR_UNKNOWN_HOST;
{$IFDEF _WIN_}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR],[host, WSAGetLastError]);
{$ELSE}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR],[host, errno]);
{$ENDIF}
result:=-7; //we can't connect
exit;
end;
ip_addr:=byte(hp.h_addr^[0])+(byte(hp.h_addr^[1])shl 8)+(byte(hp.h_addr^[2])shl 16)+(byte(hp.h_addr^[3])shl 24);
sock_addr.sin_addr:=in_addr(ip_addr);
hp.h_length:=10;
end;
sock_addr.sin_port := htons(port);
fsd:=sock;
ftype:=VIO_TYPE_TCPIP;
vio_blocking(false); //do not wait to connect as we'll get an error on read timed-out
//we resolved the address .. let's try to connect
if (connect(sock,TSockAddr(sock_addr), sizeof(sock_addr)) <0)
{$IFDEF _WIN_}and
(WSAGetLastError <>WSAEWOULDBLOCK){$ELSE} {and ??? errno = EWOUDLBLOCK}{$ENDIF} then
begin
fsd:=0;
ftype:=VIO_CLOSED;
ffcntl_mode:=0; //reset mode
flast_errno:= CR_CONN_HOST_ERROR;
{$IFDEF _WIN_}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR], [host, WSAGetLastError]);
{$ELSE}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR], [host, errno]);
{$ENDIF}
result:=-6; //we can't connect
exit;
end;
fastsend; //attempt to use fastsend
keepalive(TRUE);
//are we really connected?
if (ftimeout<>0)and(not fNoTimeOut)and(not vio_poll_read(ftimeout)) then
begin //if we don't get anything during time out
fsd:=0;
ftype:=VIO_CLOSED;
ffcntl_mode:=0; //reset mode
flast_errno:= CR_CONN_HOST_ERROR;
{$IFDEF _WIN_}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR], [host, WSAGetLastError]);
{$ELSE}
flast_error:=format(client_errors[(flast_errno)-CR_MIN_ERROR], [host, errno]);
{$ENDIF}
result:=-7; //we can't connect
exit;
end;
end;
fhPipe:=0;
result:=0;//no errors and we are connected (we can start talking to the server)
flast_error:='';
flast_errno:=0;
end
else //vio allready open
result:=-20;
end;
////////////////////////////////////////////////////////////////////////////////
// poll read via select
// waits a specific interval to read something
function TMysqlVio.vio_poll_read(timeout: cardinal): boolean;
var fds:TPollFD;
res:longint;
begin
if (ftype = VIO_TYPE_NAMEDPIPE) then
begin
result:=true;
exit;
end;
if (ftype <> VIO_CLOSED) then //is vio connected?
begin
fds.fd:=fsd;
fds.revents:=0;
fds.events:=POLLIN;
{$IFDEF NEVERENABLEME}
if timeout=0 then
res:=poll({$IFNDEF _WIN_}@{$ENDIF}fds,{$IFNDEF _WIN_}1,{$ENDIF}100)//0.1 seconds for timed out on clear net
else
{$ENDIF}
res:=poll({$IFNDEF _WIN_}@{$ENDIF}fds,{$IFNDEF _WIN_}1,{$ENDIF}timeout*1000);
if res<0 then
result:=false //don't return true on errors
else
if res=0 then
result:=true
else
if fds.revents AND POLLIN = POLLIN then
result:=false
else
result:=true;
end
else //vio is not connected return false
result:=false;
{$IFNDEF _WIN_}
result:=not result;
{$ENDIF}
end;
////////////////////////////////////////////////////////////////////////////////
// reads "size" bytes into a buffer "buf" from socket/pipe
function TMysqlVio.vio_read(buf: pointer; const sz: Integer): longint;
{$IFDEF _WIN_}
var len1:longword;
{$ENDIF}
begin
if (ftype <> VIO_CLOSED) then //vio is connected we can receive
begin
{$IFDEF HAVE_SSL}
if (ftype =VIO_TYPE_SSL) then //if vio is ssl
begin
//errno = 0;
result := SSL_read(fssl, buf^, sz);
if ( result<= 0) then
result:=- SSL_get_error(fssl, result); //- because the errors are positive and it may look as we send "errno" bytes
exit;
end;
{$ENDIF}
{$IFDEF _WIN_}
//extra check since in windows we can use pipes rather than sockets
if (ftype = VIO_TYPE_NAMEDPIPE)then
begin
//if it is pipe we read from it
if not(ReadFile(fhPipe, buf^, sz, len1, nil)) then
result:=-1
else
result:=len1;
end
else //we read via socket
//don't wait forever to read
if fNoTimeOut then //no pool - one should not use this unless very reliable connection
result := recv(fsd, buf^, sz,0)
else
if vio_poll_read(ftimeout) then //22-03-2002
result:=recv(fsd, buf^, sz,0)
else //22-03-2002
result:=-1; //22-03-2002
{$ELSE}
//we don't have pipes on linux .. so just read from socket
errno:=0;
//don't wait forever to read
if fNoTimeOut then //no pool - one should not use this unless very reliable connection
result := recv(fsd, buf^, sz,0)
else
if vio_poll_read(ftimeout) then //22-03-2002
result := recv(fsd, buf^, sz,0)
else //22-03-2002
result:=-1; //22-03-2002
{$ENDIF}
end
else //vio not connected returns -1
result:=-1;
end;
////////////////////////////////////////////////////////////////////////////////
// returns true if we should try again to read/write
function TMysqlVio.vio_should_retry: boolean;
var en:longint;
begin
if (ftype <> VIO_CLOSED) then //vio is connected
begin
//get last error
{$IFDEF _WIN_}
en:=WSAGetLastError;
{$ELSE}
en:=errno;
{$ENDIF}
//check if we should retry
{$IFDEF _WIN_}
result:= (en=WSAEINPROGRESS)or(en=WSAEINTR)or(en=WSAEWOULDBLOCK);
{$ELSE}
result:= (en = EAGAIN) or (en = EINTR);
{$ENDIF}
end
else //vio is not connected .. no point to retry
result:=false;
end;
////////////////////////////////////////////////////////////////////////////////
// writes "size" bytes from a buffer "buf" to socket/pipe
function TMysqlVio.vio_write(buf: pointer; size: Integer): longint;
{$IFDEF _WIN_}
var len1:longword;
{$ENDIF}
begin
if (ftype <> VIO_CLOSED) then //if vio is connected
begin
{$IFDEF HAVE_SSL}
if (ftype =VIO_TYPE_SSL) then //if vio is ssl
begin
result := SSL_write(fssl, pchar(buf^)^, size);
exit;
end;
{$ENDIF}
{$IFDEF _WIN_}
//extra check since in windows we can use pipes rather than sockets
if (ftype = VIO_TYPE_NAMEDPIPE) then
begin
//if it is pipe we write into it
if not(WriteFile(fhPipe, pchar(buf^)^, size, len1, nil)) then
result:=-1
else
result:=len1;
end
else //we send via socket
result:=send(fsd, pchar(buf^)^, size,0);
{$ELSE}
//we don't have pipes on linux .. so just write to socket
errno:=0;
result := send(fsd, pchar(buf^)^, size,0);
{$ENDIF}
end
else //vio not connected returns -1 allways
result:=-1;
end;
////////////////////////////////////////////////////////////////////////////////
// set wVersion to 0 as initial value
// any other value in finalization will call WSACleanup
// Note: only for windows
initialization
begin
{$IFDEF _WIN_}
fWsaData.wVersion:=0;
{$ENDIF}
end;
////////////////////////////////////////////////////////////////////////////////
// if wVersion is <> 0 we need to clean winsock
// Note: only for windows
finalization
begin
{$IFDEF _WIN_}
if fWsaData.wVersion<>0 then
WSACleanup;
{$ENDIF}
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -