开发者

Translate Code: C Socket to PHP Socket

I looked through past threads on here to find any relevant topics regarding C sockets being translated to PHP sockets, and I've ready extensively on php.net and C tutorials to figure out how to convert some C source code I have into PHP source code involving a remote socket connection.

The source I am going to post is in C. This code is already working and confirmed to work in a compiled .exe that one of my programmers wrote. He doesn't know PHP, which I am creating this new program in that requires this snippet.

The program does this: It creates a socket connection to a remote server/port, sends the filesize of an image that it needs to send to the server, then I am guessing when the server knows the filesize, the program sends the binary image data and the filesize of the image again (like an upload feature to the server via sockets). Then it uses the recv(); function in C to receive the bytes back of a specific length.

Basically it is sending a picture with something encrypted inside of it. The server already has a program running on it on the specified port that is decrypting the image. Then the socket is sending back that decrypted text. I do not have access to the algorithm for decryption o开发者_开发问答therwise I would not be using sockets obviously.

Here is the C source I was sent, and my subsequent attempts in PHP to translate it properly.

// In the this C code, there is the long size; variable that is used at the bottom but is never initialized. I don't know what to do with it. Some other variables are never used either.

function picBin()
assume curlBinaryData variable pic is filled with binary data from picture download.
pic->currentSize is set to the size of the image

it will return 0 if successful. also char *word in the function's params will be set to the pic's decryption

//bin data structure i use for a quick ghetto download function, just so you know how it looks

struct curlBinaryData{
    char *data;
    int currentSize;
    int maxSize;
};

int picBin(curlBinaryData *pic, char *word, int threadNum,
           char *host, unsigned short port)
{
    char data1[1000], data2[1000],
         temp[1000], printBuf[1000], buffer[1000], *p, *p2;
    int num, a, totalBytes;
    long size;
    char *pSize;
    SOCKET sock;

    while ((sock = connectSocket(host, port)) == INVALID_SOCKET)
    {
        sprintf(printBuf, "Could not connect(picBin) %s:%d\n", host, port);
        print_ts(printBuf, "red");
        //Sleep(15000);
    }

    buffer[0]='\0';
    send(sock, buffer, 1, 0);

    pSize=(char *)&(pic->currentSize);
    send(sock, pSize, 4, 0);

    send(sock, pic->data, pic->currentSize, 0);

    totalBytes=0;
    do{ 
        if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
            totalBytes+=num;
    } while( (totalBytes<4) && (num>0) );

    pSize=(char *)&size;
    if (totalBytes==4){ //got 4 bytes for dword
        memcpy(pSize, data1, 4);
        if (size==1)
        {
            totalBytes=0;
            do
            {
                if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
                    totalBytes+=num;
            } while( (totalBytes<4) && (num>0) );
            memcpy(pSize, data1, 4);
            if (totalBytes==4)
            { //got 4 bytes for dword
                totalBytes=0;
                for (a=0; ( (a<size) && (num>0) ); a++)
                {
                    if ( (num=recv(sock, data1+totalBytes, 1, 0)) > 0)
                        totalBytes+=num;
                }
                if (totalBytes==size)
                {
                    closesocket(sock);
                    data1[totalBytes]='\0';
                    strcpy(word, data1);

                    return 0; //0 on success
                }
            }
        }
    }
    closesocket(sock);
    return -1; //something errord
}

Now here is my PHP code I attempted:

if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
{
  echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}

if (socket_connect($sock, $host, $port) === false)
{
  echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

socket_send($sock, '\0', 1, MSG_EOF);

$ci = file_get_contents($picURL);
$ciwrite = fopen('pic.jpg', 'w+');
fwrite($ciwrite, $ci);
fclose($ciwrite);

$picFileSize = filesize('pic.jpg');

socket_send($sock, $picFileSize, 4, MSG_EOF);

socket_send($sock, $ci, $picFileSize, MSG_EOF);

$num = socket_recv($sock, $totalBytes, 1, MSG_DONTWAIT);

print $num; // this doesn't even Print anything to my console when I execute it via CLI

/*do{
    if (($num = socket_recv($sock, $totalBytes, 1)) > 0)
    {
      $totalBytes += $num;
    }
  } while(($totalBytes &lt; 4) && ($num > 0));*/


    buffer[0]='\0';
    send(sock, buffer, 1, 0);

socket_send($sock, '\0', 1, MSG_EOF);

Backslash escape sequences other than \' and \\ are not expanded in single quoted strings; thus, '\0' is a string of the two characters \ and 0, and the above socket_send() sends the character \.
MSG_EOF is without effect at best and harmful at worst; better don't use it.
A correct translation is:

  socket_send($sock, "\0", 1, 0);
    pSize=(char *)&(pic->currentSize);
    send(sock, pSize, 4, 0);

socket_send($sock, $picFileSize, 4, MSG_EOF);

The above socket_send() sends the first 4 characters of the ASCII string representation of $picFileSize, because socket_send() expects a string as its second argument and thus the given integer is coerced into a string. To send a 4-byte binary integer:

  socket_send($sock, pack("L", $picFileSize), 4, 0);
$num = socket_recv($sock, $totalBytes, 1, MSG_DONTWAIT);

print $num; // this doesn't even Print anything to my console when I execute it via CLI

It's no wonder that you get no data if you DONTWAIT for it.
A working translation for the receive part of the C program is:

$totalBytes = socket_recv($sock, $data1, 4, MSG_WAITALL);
if ($totalBytes==4)
{ //got 4 bytes for dword
    $size = unpack("L", $data1);
    if ($size[1]==1)
    {
        $totalBytes = socket_recv($sock, $data1, 4, MSG_WAITALL);
        if ($totalBytes==4)
        { //got 4 bytes for dword
            $size = unpack("L", $data1);
            $totalBytes = socket_recv($sock, $data1, $size[1], MSG_WAITALL);
            if ($totalBytes==$size[1])
            {
                echo $data1, "\n";
            }
        }
    }
}


regarding C sockets being translated to PHP sockets

Sockets are implemented by the OS - not the language. There is no such thing as a C socket nor a PHP socket.

When you invoke socket_send from PHP it converts the message to a string (if it's not already one).

pSize=(char *)&(pic->currentSize);
send(sock, pSize, 4, 0);

WTF? Assuming that pic->currentSize contains a string represenation if the image why is it hard coded to 4 bytes!

But here:

send(sock, pic->data, pic->currentSize, 0);

pic->currentSize must contain an integer value. Shoving (char *) in front of a pointer to an integer (or a long, since that appears to be how 'size' is declared) DOES NOT MAKE IT a string. It's still a pointer. OK a 32 bit pointer will be 4 bytes - but WTF is a pointer being sent over a socket??? Unless there's some weird overloading going on here and this is actually C++ rather than C.

Reading further on it sends the pointer to the remote end then reads back a 4 byte value and considers the operation successful if it matches the pointer....!! AAARRGGHHH! even if it were sending the size, this level of integrity checking is entirely redundant over a Unix or INET socket.

I'd dig some more but it's going to be a waste of time trying to make sense of this C code. Use a network sniffer to work out what's really happenning here; do not use this C code as any sort of model of how to write your own client.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜