Initial checkin of libxpnet developed on Linux and ported to Windows.

(Not part of build.  Awaiting sr.)

b = 63835
r = ssu,dbragg
This commit is contained in:
sgehani%netscape.com 2000-12-28 00:27:10 +00:00
Родитель f33c846ab9
Коммит 2bda2ee4fc
13 изменённых файлов: 2287 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,34 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = src test
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,30 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
DEPTH=..\..\..
DIRS=src test
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -0,0 +1,44 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VAPTH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = xpnet
LIBRARY_NAME = xpnet_s
CPPSRCS = \
nsSocket.cpp \
nsFTPConn.cpp \
nsHTTPConn.cpp \
$(NULL)
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,48 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
MODULE=xpnet
LIBNAME=$(MODULE)
DEPTH=..\..\..\..
MAKE_OBJ_TYPE=DLL
LIBRARY=$(OBJDIR)\$(LIBNAME)_s.lib
OBJS= \
.\$(OBJDIR)\nsSocket.obj \
.\$(OBJDIR)\nsFTPConn.obj \
.\$(OBJDIR)\nsHTTPConn.obj \
$(NULL)
include <$(DEPTH)/config/rules.mak>
install::
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
$(RM) $(DIST)\lib\$(LIBNAME)_s.lib
clobber_all:: clobber

Просмотреть файл

@ -0,0 +1,496 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#ifdef __unix
#include <sys/param.h>
#elif defined(_WINDOWS)
#include <windows.h>
#define MAXPATHLEN MAX_PATH
#endif
#include "nsSocket.h"
#include "nsFTPConn.h"
const int kCntlPort = 21;
const int kDataPort = 20;
const int kCmdBufSize = 64 + MAXPATHLEN;
const int kRespBufSize = 1024;
const int kKilobyte = 1024;
const int kUsecsPerSec = 1000000;
const int kDlBufSize = 1024;
nsFTPConn::nsFTPConn(char *aHost) :
mHost(aHost),
mState(CLOSED),
mPassive(FALSE),
mCntlSock(NULL),
mDataSock(NULL)
{
}
nsFTPConn::~nsFTPConn()
{
// don't release mHost cause we don't own it
}
int
nsFTPConn::Open()
{
int err = OK;
char cmd[kCmdBufSize], resp[kRespBufSize];
int respBufSize = kRespBufSize;
if (!mHost)
return E_PARAM;
if (mState != CLOSED)
return E_ALREADY_OPEN;
/* open control connection on port 21 */
mCntlSock = new nsSocket(mHost, kCntlPort);
if (!mCntlSock)
return E_MEM;
ERR_CHECK(mCntlSock->Open());
ERR_CHECK(mCntlSock->Recv((unsigned char *)resp, &respBufSize));
DUMP(resp);
/* issue USER command on control connection */
sprintf(cmd, "USER anonymous\r\n");
err = IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
/* issue PASS command on control connection */
sprintf(cmd, "PASS -linux@installer.sbg\r\n");
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
mState = OPEN;
return err;
BAIL:
if (mCntlSock)
{
mCntlSock->Close();
delete mCntlSock;
mCntlSock = NULL;
}
if (mDataSock)
{
mDataSock->Close();
delete mDataSock;
mDataSock = NULL;
}
return err;
}
int
nsFTPConn::Open(char *aHost)
{
if (!aHost)
return E_PARAM;
mHost = aHost;
return Open();
}
int
nsFTPConn::Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
FTPGetCB aCBFunc)
{
struct stat dummy;
int err = OK, wrote = 0, totBytesRd = 0;
char cmd[kCmdBufSize], resp[kRespBufSize];
int fileSize = 0, respBufSize = kRespBufSize;
FILE *loclfd = NULL;
if (!aSrvPath || !aLoclPath)
return E_PARAM;
if (mState != OPEN || !mCntlSock)
return E_NOT_OPEN;
/* stat local path and verify aOvWrite is set if file already exists */
err = stat(aLoclPath, &dummy);
if (err != -1 && aOvWrite == FALSE)
return E_CANT_OVWRITE;
mState = GETTING;
/* initialize data connection */
ERR_CHECK(DataInit(mHost, kDataPort, &mDataSock));
/* issue SIZE command on control connection */
sprintf(cmd, "SIZE %s\r\n", aSrvPath);
err = IssueCmd(cmd, resp, kRespBufSize, mCntlSock); /* non-fatal */
if (err == OK && (resp[0] == '2'))
fileSize = atoi(&resp[4]);
/* issue TYPE command on control connection */
sprintf(cmd, "TYPE %s\r\n", aType==BINARY ? "I" : "A");
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
/* issue RETR command on control connection */
sprintf(cmd, "RETR %s\r\n", aSrvPath);
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
/* get file contents on data connection */
if (!mPassive)
ERR_CHECK(mDataSock->SrvAccept());
/* initialize locl file */
if (!(loclfd = fopen(aLoclPath, aType==BINARY ? "wb" : "w")) ||
(fseek(loclfd, 0, SEEK_SET) != 0))
{
err = E_LOCL_INIT;
goto BAIL;
}
totBytesRd = 0;
do
{
respBufSize = kDlBufSize;
err = mDataSock->Recv((unsigned char *)resp, &respBufSize);
if (err != nsSocket::E_READ_MORE &&
err != nsSocket::E_EOF_FOUND &&
err != nsSocket::OK)
goto BAIL;
totBytesRd += respBufSize;
if (err == nsSocket::E_READ_MORE && aCBFunc)
aCBFunc(totBytesRd, fileSize);
/* append to local file */
wrote = fwrite((void *)resp, 1, respBufSize, loclfd);
if (wrote != respBufSize)
{
err = E_WRITE;
goto BAIL;
}
}
while (err == nsSocket::E_READ_MORE || err == nsSocket::OK);
if (err == nsSocket::E_EOF_FOUND)
err = OK;
BAIL:
/* close locl file if open */
if (loclfd)
fclose(loclfd);
/* kill data connection if it exists */
if (mDataSock)
{
mDataSock->Close();
delete mDataSock;
mDataSock = NULL;
}
mState = OPEN;
mPassive = FALSE;
return err;
}
int
nsFTPConn::Close()
{
int err = OK;
if (mState != OPEN)
return E_NOT_OPEN;
/* close sockets */
if (mCntlSock)
{
ERR_CHECK(mCntlSock->Close());
delete mCntlSock;
mCntlSock = NULL;
}
if (mDataSock)
{
ERR_CHECK(mDataSock->Close());
delete mDataSock;
mDataSock = NULL;
}
BAIL:
return err;
}
int
nsFTPConn::IssueCmd(char *aCmd, char *aResp, int aRespSize, nsSocket *aSock)
{
int err = OK;
int len;
/* param check */
if (!aSock || !aCmd || !aResp || aRespSize <= 0)
return E_PARAM;
/* send command */
len = strlen(aCmd);
ERR_CHECK(aSock->Send((unsigned char *)aCmd, &len));
DUMP(aCmd);
/* receive response */
do
{
err = aSock->Recv((unsigned char *)aResp, &aRespSize);
if (err != nsSocket::OK &&
err != nsSocket::E_READ_MORE &&
err != nsSocket::E_EOF_FOUND)
goto BAIL;
DUMP(aResp);
}
while (err == nsSocket::E_READ_MORE);
/* alternate interpretation of err codes */
if ( (strncmp(aCmd, "APPE", 4) == 0) ||
(strncmp(aCmd, "LIST", 4) == 0) ||
(strncmp(aCmd, "NLST", 4) == 0) ||
(strncmp(aCmd, "REIN", 4) == 0) ||
(strncmp(aCmd, "RETR", 4) == 0) ||
(strncmp(aCmd, "STOR", 4) == 0) ||
(strncmp(aCmd, "STOU", 4) == 0) )
{
switch (*aResp)
{
case '1': /* exception: 100 series is OK */
case '2':
break;
case '3':
err = E_CMD_ERR;
break;
case '4':
case '5':
err = E_CMD_FAIL;
break;
default:
err = E_CMD_UNEXPECTED;
break;
}
}
/* regular interpretation of err codes */
else
{
switch (*aResp)
{
case '2':
break;
case '1':
case '3':
err = E_CMD_ERR;
break;
case '4':
case '5':
err = E_CMD_FAIL;
break;
default:
err = E_CMD_UNEXPECTED;
break;
}
}
BAIL:
return err;
}
int
nsFTPConn::ParseAddr(char *aBuf, char **aHost, int *aPort)
{
int err = OK;
char *c;
int addr[6];
/* param check */
if (!aBuf || !aHost || !aPort)
return E_PARAM;
c = aBuf + strlen("227 "); /* pass by return code */
while (!isdigit((int)(*c)))
{
if (*c == '\0')
return E_INVALID_ADDR;
c++;
}
if (sscanf(c, "%d,%d,%d,%d,%d,%d",
&addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6)
return E_INVALID_ADDR;
*aHost = (char *)malloc(strlen("XXX.XXX.XXX.XXX"));
sprintf(*aHost, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
*aPort = ((addr[4] & 0xFF) << 8) | (addr[5] & 0xFF);
#ifdef DEBUG
printf("%s %d: PASV response: %d,%d,%d,%d,%d,%d\n", __FILE__, __LINE__,
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
printf("%s %d: Host = %s\tPort = %d\n", __FILE__, __LINE__, *aHost, *aPort);
#endif
return err;
}
int
nsFTPConn::DataInit(char *aHost, int aPort, nsSocket **aSock)
{
int err = OK;
char cmd[kCmdBufSize], resp[kRespBufSize];
char *srvHost = NULL;
int srvPort = 0;
char *hostPort = NULL;
/* param check */
if (!aHost || !aSock)
return E_PARAM;
/* issue PASV command */
sprintf(cmd, "PASV\r\n");
err = IssueCmd(cmd, resp, kRespBufSize, mCntlSock);
if (err != OK)
{
err = OK;
goto ACTIVE; /* failover to active mode */
}
mPassive = TRUE;
ERR_CHECK(ParseAddr(resp, &srvHost, &srvPort));
*aSock = new nsSocket(srvHost, srvPort);
if (!*aSock)
{
err = E_MEM;
goto BAIL;
}
ERR_CHECK((*aSock)->Open());
if (srvHost)
{
free(srvHost);
srvHost = NULL;
}
return err;
ACTIVE:
*aSock = new nsSocket(aHost, aPort);
if (!*aSock)
{
err = E_MEM;
goto BAIL;
}
/* init data socket making it listen */
ERR_CHECK((*aSock)->SrvOpen());
ERR_CHECK((*aSock)->GetHostPortString(&hostPort)); // allocates
if (!hostPort)
{
err = E_MEM;
goto BAIL;
}
sprintf(cmd, "PORT %s\r\n", hostPort);
ERR_CHECK(IssueCmd(cmd, resp, kRespBufSize, mCntlSock));
BAIL:
if (mPassive && err != OK)
mPassive = FALSE;
if (err != OK && (*aSock))
{
delete *aSock;
*aSock = NULL;
}
if (srvHost)
{
free(srvHost);
srvHost = NULL;
}
if (hostPort)
{
free(hostPort);
hostPort = NULL;
}
return err;
}
#ifdef TEST_NSFTPCONN
static struct timeval init;
int
TestFTPGetCB(int aBytesRd, int aTotal)
{
struct timeval now;
float rate;
gettimeofday(&now, NULL);
rate = nsSocket::CalcRate(&init, &now, aBytesRd);
printf("br=%d\ttot=%d\trt=%f\tirt=%d\n",aBytesRd, aTotal, rate, (int)rate);
return 0;
}
int
main(int argc, char **argv)
{
int err = nsFTPConn::OK;
nsFTPConn *conn = 0;
char *leaf = NULL;
if (argc < 2)
{
printf("usage: %s <host> <path/on/server>\n", argv[0]);
exit(0);
}
if ((leaf = strrchr(argv[2], '/'))) leaf++;
else leaf = argv[2];
conn = new nsFTPConn(argv[1]);
printf("Opening connection to %s...\n", argv[1]);
err = conn->Open();
if (err != nsFTPConn::OK) { printf("error: %d\n", err); exit(err); }
printf("Getting binary file %s...\n", argv[2]);
gettimeofday(&init, NULL);
err = conn->Get(argv[2], leaf, nsFTPConn::BINARY, TRUE, TestFTPGetCB);
if (err != nsFTPConn::OK) { printf("error: %d\n", err); exit(err); }
printf("Closing connection to %s...\n", argv[1]);
err = conn->Close();
if (err != nsFTPConn::OK) { printf("error: %d\n", err); exit(err); }
printf("Test successful!\n");
exit(err);
}
#endif /* TEST_NSFTPCONN */

Просмотреть файл

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#ifndef _NS_FTPCONN_H_
#define _NS_FTPCONN_H_
class nsSocket;
typedef int (*FTPGetCB)(int aBytesRd, int aTotal);
class nsFTPConn
{
public:
nsFTPConn(char *aHost);
~nsFTPConn();
/* ftp type */
enum
{
ASCII = 0,
BINARY
};
/* connection state */
enum
{
OPEN = 0,
GETTING,
CLOSED
};
int Open();
int Open(char *aHost);
int Get(char *aSrvPath, char *aLoclPath, int aType, int aOvWrite,
FTPGetCB aCBFunc);
int Close();
/*--------------------------------------------------------------------*
* Errors
*--------------------------------------------------------------------*/
enum
{
OK = 0,
E_MEM = -801, /* out of memory */
E_PARAM = -802, /* parameter null or incorrect */
E_ALREADY_OPEN = -803, /* connection already established */
E_NOT_OPEN = -804, /* connection not established, can't use */
E_CMD_ERR = -805, /* ftp command error */
E_CMD_FAIL = -806, /* ftp command failed */
E_CMD_UNEXPECTED = -807, /* ftp command unexpected response */
E_WRITE = -808, /* write to socket/fd failed */
E_READ = -809, /* read on socket/fd failed */
E_SMALL_BUF = -810, /* buffer too small, provide bigger one */
E_CANT_OVWRITE = -811, /* cannot overwrite existing file */
E_LOCL_INIT = -812, /* local file open/init failed */
E_INVALID_ADDR = -814 /* couldn't parse address/port */
};
private:
int IssueCmd(char *aCmd, char *aResp, int aRespSize,
nsSocket *aSock);
int ParseAddr(char *aBuf, char **aHost, int *aPort);
int DataInit(char *aHost, int aPort, nsSocket **aSock);
char *mHost;
int mState;
int mPassive;
nsSocket *mCntlSock;
nsSocket *mDataSock;
};
#ifndef NULL
#define NULL (void*)0L
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef DUMP
#undef DUMP
#endif
#if defined(DEBUG) || defined(DEBUG_sgehani)
#define DUMP(_msg) printf("%s %d: %s\n", __FILE__, __LINE__, _msg);
#else
#define DUMP(_msg)
#endif /* DEBUG */
#ifndef ERR_CHECK
#define ERR_CHECK(_func) \
do { \
err = _func; \
if (err != OK) \
goto BAIL; \
} while(0);
#endif
#endif /* _NS_FTPCONN_H_ */

Просмотреть файл

@ -0,0 +1,598 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
#include "nsHTTPConn.h"
#include "nsSocket.h"
const char kHTTPProto[8] = "http://";
const char kFTPProto[8] = "ftp://";
const int kHTTPPort = 80;
const int kFTPPort = 21;
const int kRespBufSize = 1024;
const int kReqBufSize = 1024;
const int kHdrBufSize = 256;
const char kCRLF[3] = "\r\n";
const char kHdrBodyDelim[5] = "\r\n\r\n";
const char kDefaultDestFile[11] = "index.html";
nsHTTPConn::nsHTTPConn(char *aHost, int aPort, char *aPath) :
mHost(aHost),
mPath(aPath),
mProxiedURL(NULL),
mProxyUser(NULL),
mProxyPswd(NULL),
mDestFile(NULL),
mHostPathAllocd(FALSE),
mSocket(NULL)
{
if (aPort <= 0)
mPort = kHTTPPort;
else
mPort = aPort;
DUMP(("mHost = %s\n", mHost));
DUMP(("mPort = %d\n", mPort));
DUMP(("mPath = %s\n", mPath));
}
nsHTTPConn::nsHTTPConn(char *aURL) :
mPort(kHTTPPort),
mProxiedURL(NULL),
mProxyUser(NULL),
mProxyPswd(NULL),
mDestFile(NULL),
mHostPathAllocd(FALSE),
mSocket(NULL)
{
// parse URL
if (ParseURL(kHTTPProto, aURL, &mHost, &mPort, &mPath) == OK)
mHostPathAllocd = TRUE;
else
{
mHost = NULL;
mPath = NULL;
}
DUMP(("mHost = %s\n", mHost));
DUMP(("mPort = %d\n", mPort));
DUMP(("mPath = %s\n", mPath));
}
nsHTTPConn::~nsHTTPConn()
{
if (mHostPathAllocd)
{
if (mHost)
free(mHost);
if (mPath)
free(mPath);
}
}
int
nsHTTPConn::Open()
{
// verify host && path
if (!mHost || !mPath)
return E_MALFORMED_URL;
// create socket
mSocket = new nsSocket(mHost, mPort);
if (!mSocket)
return E_MEM;
// open socket
return mSocket->Open();
}
int
nsHTTPConn::Get(HTTPGetCB aCallback, char *aDestFile)
{
int rv;
char *pathToUse;
// verify host && path
if (!mHost || !mPath)
return E_MALFORMED_URL;
if (!aDestFile)
{
if (mProxiedURL)
pathToUse = mProxiedURL;
else
pathToUse = mPath;
// no leaf: assume default file 'index.html'
if (*(pathToUse + strlen(pathToUse) - 1) == '/')
aDestFile = (char *) kDefaultDestFile;
else
aDestFile = strrchr(pathToUse, '/') + 1;
}
// issue request
rv = Request();
// recv response
if (rv == OK)
rv = Response(aCallback, aDestFile);
return rv;
}
int
nsHTTPConn::Close()
{
int rv;
// close socket
rv = mSocket->Close();
// destroy socket
delete mSocket;
return rv;
}
void
nsHTTPConn::SetProxyInfo(char *aProxiedURL, char *aProxyUser,
char *aProxyPswd)
{
mProxiedURL = aProxiedURL;
mProxyUser = aProxyUser;
mProxyPswd = aProxyPswd;
}
int
nsHTTPConn::Request()
{
char req[kReqBufSize];
char hdr[kHdrBufSize];
int rv;
memset(req, 0, kReqBufSize);
// format header buf:
// request line
memset(hdr, 0, kHdrBufSize);
if (mProxiedURL)
{
sprintf(hdr, "GET %s HTTP/1.1%s", mProxiedURL, kCRLF);
strcpy(req, hdr);
memset(hdr, 0, kHdrBufSize);
if (strncmp(mProxiedURL, kFTPProto, strlen(kFTPProto)) == 0)
{
char *ftpHost, *ftpPath;
int ftpPort = kFTPPort;
rv = ParseURL(kFTPProto, mProxiedURL,
&ftpHost, &ftpPort, &ftpPath);
if (rv == OK)
sprintf(hdr, "Host: %s:%d%s", ftpHost, ftpPort, kCRLF);
if (ftpHost)
free(ftpHost);
if (ftpPath)
free(ftpPath);
}
else
sprintf(hdr, "Host: %s%s", mHost, kCRLF);
strcat(req, hdr);
}
else
{
sprintf(hdr, "GET %s HTTP/1.1%s", mPath, kCRLF);
strcpy(req, hdr);
memset(hdr, 0, kHdrBufSize);
sprintf(hdr, "Host: %s%s", mHost, kCRLF);
strcat(req, hdr);
}
// if proxy set and proxy user/pswd set
if (mProxyUser && mProxyPswd)
{
char *usrPsd = (char *) malloc(strlen(mProxyUser) +
strlen(":") +
strlen(mProxyPswd));
if (!usrPsd)
return E_MEM;
sprintf(usrPsd, "%s:%s", mProxyUser, mProxyPswd);
// base 64 encode proxy header
char usrPsdEncoded[128]; // pray that 128 is long enough
memset(usrPsdEncoded, 0, 128);
DUMP(("Unencoded string: %s\n", usrPsd));
rv = Base64Encode((const unsigned char *)usrPsd, strlen(usrPsd),
usrPsdEncoded, 128);
DUMP(("Encoded string: %s\n", usrPsdEncoded));
DUMP(("Base64Encode returned: %d\n", rv));
if (rv <= 0)
{
return E_B64_ENCODE;
}
// append proxy header to header buf
memset(hdr, 0, kHdrBufSize);
sprintf(hdr, "Proxy-authorization: Basic %s%s", usrPsdEncoded, kCRLF);
strcat(req, hdr);
// XXX append host with port 21 if ftp
}
// headers all done so indicate
strcat(req, kCRLF);
// send header buf over socket
int bufSize = strlen(req);
rv = mSocket->Send((unsigned char *) req, &bufSize);
DUMP(("\n\n%s", req));
if (bufSize != (int) strlen(req))
rv = E_REQ_INCOMPLETE;
return rv;
}
int
nsHTTPConn::Response(HTTPGetCB aCallback, char *aDestFile)
{
// NOTE: overwrites dest file if it already exists
int rv = OK;
char resp[kRespBufSize];
int bufSize, fwriteLen, fwrote, bytesWritten = 0, expectedSize = 0;
FILE *destFd;
char *fwritePos;
int bFirstIter = TRUE;
if (!aDestFile)
return E_PARAM;
// open dest file
destFd = fopen(aDestFile, "w+");
if (!destFd)
return E_OPEN_FILE;
// iteratively recv response
do
{
memset(resp, 0, kRespBufSize);
bufSize = kRespBufSize;
rv = mSocket->Recv((unsigned char *) resp, &bufSize);
DUMP((resp));
DUMP(("nsSocket::Recv returned: %d\t and recd: %d\n", rv, bufSize));
if (bFirstIter)
{
fwritePos = strstr(resp, kHdrBodyDelim);
if (fwritePos == NULL)
{
// XXX no header! should we handle?
fwritePos = resp;
fwriteLen = bufSize;
}
else
{
ParseContentLength((const char *)resp, &expectedSize);
// move past hdr-body delimiter
fwritePos += strlen(kHdrBodyDelim);
fwriteLen = bufSize - (fwritePos - resp);
}
bFirstIter = FALSE;
}
else
{
fwritePos = resp;
fwriteLen = bufSize;
}
fwrote = fwrite(fwritePos, sizeof(char), fwriteLen, destFd);
assert(fwrote == fwriteLen);
if (fwriteLen > 0)
bytesWritten += fwriteLen;
if (aCallback)
aCallback(bytesWritten, expectedSize);
} while (rv == nsSocket::E_READ_MORE || rv == nsSocket::OK);
if (rv == nsSocket::E_EOF_FOUND)
{
DUMP(("EOF detected\n"));
rv = OK;
}
fclose(destFd);
return rv;
}
int
nsHTTPConn::ParseURL(const char *aProto, char *aURL, char **aHost,
int *aPort, char **aPath)
{
char *pos, *nextSlash, *nextColon, *end, *hostEnd;
int protoLen = strlen(aProto);
if (!aURL || !aHost || !aPort || !aPath || !aProto)
return E_PARAM;
if ((strncmp(aURL, aProto, protoLen) != 0) ||
(strlen(aURL) < 9))
return E_MALFORMED_URL;
pos = aURL + protoLen;
nextColon = strchr(pos, ':');
nextSlash = strchr(pos, '/');
// optional port specification
if (nextColon && ((nextSlash && nextColon < nextSlash) ||
!nextSlash))
{
int portStrLen;
if (nextSlash)
portStrLen = nextSlash - nextColon;
else
portStrLen = strlen(nextColon);
char *portStr = (char *) malloc(portStrLen);
if (!portStr)
return E_MEM;
memset(portStr, 0, portStrLen);
strncpy(portStr, nextColon+1, portStrLen);
*aPort = atoi(portStr);
free(portStr);
}
if ( (!nextColon || (nextSlash && (nextColon > nextSlash)))
&& *aPort <= 0) // don't override port if already set
*aPort = -1;
// only host in URL, assume '/' for path
if (!nextSlash)
{
int copyLen;
if (nextColon)
copyLen = nextColon - pos;
else
copyLen = strlen(pos);
*aHost = (char *) malloc(copyLen + 1); // to NULL terminate
strncpy(*aHost, pos, copyLen);
*aPath = (char *) malloc(2);
*aPath = "/\0";
return OK;
}
// normal parsing: both host and path exist
if (nextColon)
hostEnd = nextColon;
else
hostEnd = nextSlash;
*aHost = (char *) malloc(hostEnd - pos + 1); // to NULL terminate
if (!*aHost)
return E_MEM;
memset(*aHost, 0, hostEnd - pos + 1);
strncpy(*aHost, pos, hostEnd - pos);
*(*aHost + (hostEnd - pos)) = 0; // NULL terminate
pos = nextSlash;
end = aURL + strlen(aURL);
*aPath = (char *) malloc(end - pos + 1);
if (!*aPath)
{
if (*aHost)
free(*aHost);
return E_MEM;
}
memset(*aPath, 0, end - pos + 1);
strncpy(*aPath, pos, end - pos);
return OK;
}
void
nsHTTPConn::ParseContentLength(const char *aBuf, int *aLength)
{
char *clHdr; // Content-length header line start
char *eol, *pos;
char clNameStr1[16] = "Content-length:";
char clNameStr2[16] = "Content-Length:";
char *clNameStr = clNameStr1;
if (!aBuf || !aLength)
return; // non fatal so no error codes returned
*aLength = 0;
// XXX strcasestr() needs to be ported for Solaris (and Win32 and Mac?)
clHdr = strstr(aBuf, (char *)clNameStr1);
if (!clHdr)
{
clHdr = strstr(aBuf, (char *)clNameStr2);
clNameStr = clNameStr2;
}
if (clHdr)
{
eol = strstr(clHdr, kCRLF); // end of line
pos = clHdr + strlen(clNameStr);
while ((pos < eol) && (*pos == ' ' || *pos == '\t'))
pos++;
if (pos < eol)
{
int clValStrLen = eol - pos + 1; // extra byte to NULL terminate
char *clValStr = (char *) malloc(clValStrLen);
if (!clValStr)
return; // imminent doom!
memset(clValStr, 0, clValStrLen);
strncpy(clValStr, pos, eol - pos);
*aLength = atoi(clValStr);
}
}
}
int
nsHTTPConn::Base64Encode(const unsigned char *in_str, int in_len,
char *out_str, int out_len)
{
// NOTE: shamelessly copied from nsAbSyncPostEngine.cpp
static unsigned char base64[] =
{
/* 0 1 2 3 4 5 6 7 */
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0 */
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 1 */
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 2 */
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 3 */
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 4 */
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 5 */
'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 6 */
'4', '5', '6', '7', '8', '9', '+', '/' /* 7 */
};
int curr_out_len = 0;
int i = 0;
unsigned char a, b, c;
out_str[0] = '\0';
if (in_len > 0)
{
while (i < in_len)
{
a = in_str[i];
b = (i + 1 >= in_len) ? 0 : in_str[i + 1];
c = (i + 2 >= in_len) ? 0 : in_str[i + 2];
if (i + 2 < in_len)
{
out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
+ ((b >> 4) & 0xf)]);
out_str[curr_out_len++] = (base64[((b << 2) & 0x3c)
+ ((c >> 6) & 0x3)]);
out_str[curr_out_len++] = (base64[c & 0x3F]);
}
else if (i + 1 < in_len)
{
out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
+ ((b >> 4) & 0xf)]);
out_str[curr_out_len++] = (base64[((b << 2) & 0x3c)
+ ((c >> 6) & 0x3)]);
out_str[curr_out_len++] = '=';
}
else
{
out_str[curr_out_len++] = (base64[(a >> 2) & 0x3F]);
out_str[curr_out_len++] = (base64[((a << 4) & 0x30)
+ ((b >> 4) & 0xf)]);
out_str[curr_out_len++] = '=';
out_str[curr_out_len++] = '=';
}
i += 3;
if((curr_out_len + 4) > out_len)
{
return(-1);
}
}
out_str[curr_out_len] = '\0';
}
return curr_out_len;
}
#ifdef TEST_NSHTTPCONN
int
TestHTTPCB(int aBytesRd, int aTotal)
{
DUMP(("Bytes rd: %d\tTotal: %d\n", aBytesRd, aTotal));
return 0;
}
int
main(int argc, char **argv)
{
nsHTTPConn *conn;
int rv = nsHTTPConn::OK;
char *proxiedURL = NULL;
char *proxyUser = NULL;
char *proxyPswd = NULL;
DUMP(("*** %s: A self-test for the nsHTTPConn class.\n", argv[0]));
if (argc < 2)
{
printf("usage: %s <http_url> [<proxied_url> [<proxy_user> ", argv[0]);
printf("<proxy_pswd>]]\n");
exit(1);
}
conn = new nsHTTPConn(argv[1]);
if (argc >= 3)
{
proxiedURL = argv[2];
}
if (argc >= 5)
{
proxyUser = argv[3];
proxyPswd = argv[4];
}
conn->SetProxyInfo(proxiedURL, proxyUser, proxyPswd);
rv = conn->Open();
DUMP(("nsHTTPConn::Open returned: %d\n", rv));
rv = conn->Get(TestHTTPCB, NULL); // NULL: local file name = URL leaf
DUMP(("nsHTTPConn::Get returned: %d\n", rv));
rv = conn->Close();
DUMP(("nsHTTPConn::Close returned: %d\n", rv));
return 0;
}
#endif /* TEST_NSHTTPCONN */

Просмотреть файл

@ -0,0 +1,102 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#ifndef _NS_HTTPCONN_H_
#define _NS_HTTPCONN_H_
class nsSocket;
typedef int (*HTTPGetCB)(int aBytesRd, int aTotal);
class nsHTTPConn
{
public:
nsHTTPConn(char *aHost, int aPort, char *aPath);
nsHTTPConn(char *aURL);
~nsHTTPConn();
int Open();
int Get(HTTPGetCB aCallback, char *aDestFile);
int Close();
void SetProxyInfo(char *aProxiedURL, char *aProxyUser,
char *aProxyPswd);
static int ParseURL(const char *aProto, char *aURL, char **aHost,
int *aPort, char **aPath);
enum
{
OK = 0,
E_MEM = -801,
E_PARAM = -802,
E_MALFORMED_URL = -803,
E_REQ_INCOMPLETE = -804,
E_B64_ENCODE = -805,
E_OPEN_FILE = -806
};
private:
int Request();
int Response(HTTPGetCB aCallback, char *aDestFile);
void ParseContentLength(const char *aBuf, int *aLength);
int Base64Encode(const unsigned char *in_str, int in_len,
char *out_str, int out_len);
char *mHost;
char *mPath;
int mPort;
char *mProxiedURL;
char *mProxyUser;
char *mProxyPswd;
char *mDestFile;
int mHostPathAllocd;
nsSocket *mSocket;
};
#ifndef NULL
#define NULL ((void*) 0L);
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifdef DUMP
#undef DUMP
#endif
#if defined(DEBUG_sgehani) || defined(DEBUG)
#define DUMP(_vargs) \
do { \
printf("%s %d: ", __FILE__, __LINE__); \
printf _vargs; \
} while(0);
#else
#define DUMP(_vargs)
#endif
#endif /* _NS_HTTPCONN_H_ */

Просмотреть файл

@ -0,0 +1,450 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Platform-specific headers for socket functionality */
#ifdef __unix
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#elif defined(_WINDOWS)
#define read(_socket, _buf, _len) \
recv(_socket, (char *) _buf, _len, 0);
#define write(_socket, _buf, _len) \
send(_socket, (char *) _buf, _len, 0);
#include <winsock2.h>
#endif
#include "nsSocket.h"
#define MAXSOCKADDR 128
#include "platform.h" // for SOLARIS define
#if defined(SOLARIS) || defined(_WINDOWS)
#define socklen_t int
#endif
#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif
const int kUsecsPerSec = 1000000;
const int kTimeoutThresholdUsecs = 120 * kUsecsPerSec;
const int kTimeoutSelectUsecs = 100000;
const int kKilobyte = 1024;
const int kReadBufSize = 1024;
nsSocket::nsSocket(char *aHost, int aPort) :
mHost(aHost),
mPort(aPort),
mFd(-1),
mListenFd(-1)
{
}
nsSocket::~nsSocket()
{
// don't release mHost cause we don't own it
}
int
nsSocket::Open()
{
#ifdef _WINDOWS
/* funky windows initialization of winsock */
int err;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(4, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return E_WINSOCK;
}
#endif
int rv = OK;
struct sockaddr_in servaddr;
struct hostent *hptr = NULL;
mFd = socket(AF_INET, SOCK_STREAM, 0);
#ifdef _WINDOWS
if (mFd == INVALID_SOCKET)
{
printf("Last error: %d\n", WSAGetLastError());
}
#endif
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(mPort);
if ( (hptr = gethostbyname(mHost)) == NULL )
return E_INVALID_HOST;
memcpy(&servaddr.sin_addr, (struct in_addr **) hptr->h_addr_list[0],
sizeof(struct in_addr));
rv = connect(mFd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (rv < 0)
{
#if defined(DEBUG) && defined(__unix)
printf("ETIMEDOUT: %d\n", ETIMEDOUT);
printf("ECONNREFUSED: %d\n", ECONNREFUSED);
printf("EHOSTUNREACH: %d\n", EHOSTUNREACH);
printf("ENETUNREACH: %d\n", ENETUNREACH);
printf("connect error: %d\n", errno);
#endif /* DEBUG && __unix */
mFd = -1;
rv = E_SOCK_OPEN;
}
else
rv = OK;
return rv;
}
int
nsSocket::SrvOpen()
{
int rv = OK;
struct sockaddr_in servaddr;
/* init data socket making it listen */
mListenFd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
servaddr.sin_port = 0; /* let kernel bind an ephemeral port */
if ((bind(mListenFd, (struct sockaddr *) &servaddr, sizeof(servaddr))) != 0)
return E_BIND;
if ((listen(mListenFd, SOMAXCONN)) != 0)
return E_LISTEN;
return rv;
}
int
nsSocket::SrvAccept()
{
int rv = OK;
struct sockaddr cliaddr;
socklen_t clilen;
if (mListenFd < 0)
return E_PARAM;
clilen = sizeof(cliaddr);
mFd = accept(mListenFd, (struct sockaddr *) &cliaddr, &clilen);
if (mFd < 0)
rv = E_ACCEPT;
return rv;
}
int
nsSocket::Send(unsigned char *aBuf, int *aBufSize)
{
int rv = OK;
struct timeval seltime;
int timeout = 0;
fd_set selset;
if (!aBuf || aBufSize <= 0 || mFd < 0)
return E_PARAM;
while (timeout < kTimeoutThresholdUsecs)
{
FD_ZERO(&selset);
FD_SET(mFd, &selset);
seltime.tv_sec = 0;
seltime.tv_usec = kTimeoutSelectUsecs;
rv = select(mFd+1, NULL, &selset, NULL, &seltime);
switch (rv)
{
case -1: /* error occured! */
return errno;
case 0: /* timeout; retry */
timeout += kTimeoutSelectUsecs;
continue;
default: /* ready to write */
break;
}
if (!FD_ISSET(mFd, &selset))
{
timeout += kTimeoutSelectUsecs;
continue; /* not ready to write; retry */
}
else
break;
}
if (rv == 0)
return E_TIMEOUT;
rv = write(mFd, aBuf, *aBufSize);
if (rv <= 0)
rv = E_WRITE;
else
{
*aBufSize = rv;
rv = OK;
}
return rv;
}
int
nsSocket::Recv(unsigned char *aBuf, int *aBufSize)
{
int rv = OK;
unsigned char lbuf[kReadBufSize]; /* function local buffer */
int bytesrd = 0;
struct timeval seltime;
fd_set selset;
int bufsize;
if (!aBuf || *aBufSize <= 0 || mFd < 0)
return E_PARAM;
memset(aBuf, 0, *aBufSize);
for ( ; ; )
{
/* return if we anticipate overflowing caller's buffer */
if (bytesrd >= *aBufSize)
return E_READ_MORE;
memset(&lbuf, 0, kReadBufSize);
FD_ZERO(&selset);
FD_SET(mFd, &selset);
seltime.tv_sec = 0;
seltime.tv_usec = kTimeoutSelectUsecs;
rv = select(mFd+1, &selset, NULL, NULL, &seltime);
switch (rv)
{
case -1: /* error occured! */
return errno;
case 0: /* timeout; retry */
continue;
default: /* ready to read */
break;
}
// XXX TODO: prevent inf loop returning at kTimeoutThresholdUsecs
if (!FD_ISSET(mFd, &selset))
continue; /* not ready to read; retry */
bufsize = *aBufSize - bytesrd;
rv = read(mFd, lbuf, bufsize);
if (rv == 0) /* EOF encountered */
{
rv = E_EOF_FOUND;
break;
}
if (rv < 0)
{
rv = E_READ;
break;
}
if (*aBufSize >= bytesrd + rv)
{
memcpy(aBuf + bytesrd, lbuf, rv);
bytesrd += rv;
if (rv <= bufsize)
{
FD_ZERO(&selset);
FD_SET(mFd, &selset);
seltime.tv_sec = 0;
seltime.tv_usec = kTimeoutSelectUsecs;
/* check if we still need to read from this socket */
rv = select(mFd+1, &selset, NULL, NULL, &seltime);
if (rv == 1)
rv = E_READ_MORE;
else
rv = OK;
break;
}
}
else
{
rv = E_SMALL_BUF;
break;
}
}
*aBufSize = bytesrd;
return rv;
}
int
nsSocket::Close()
{
int rv = OK, rv1 = OK, rv2 = OK;
rv1 = shutdown(mFd, SHUT_RDWR);
if (mListenFd > 0)
rv2 = shutdown(mListenFd, SHUT_RDWR);
if (rv1 != 0 || rv2 != 0)
rv = E_SOCK_CLOSE;
/* funky windows shutdown of winsock */
#ifdef _WINDOWS
int wsaErr = WSACleanup();
if (wsaErr != 0)
rv = wsaErr;
#endif
return rv;
}
int
nsSocket::GetHostPortString(char **aHostPort)
{
int rv = OK;
socklen_t salen;
struct sockaddr_in servaddr;
int hpsLen; // host-port string length
if (!aHostPort)
return E_PARAM;
salen = MAXSOCKADDR;
if ((getsockname(mListenFd, (struct sockaddr *) &servaddr, &salen)) < 0)
{
*aHostPort = NULL;
return E_GETSOCKNAME;
}
hpsLen = strlen("AA1,AA2,AA3,AA4,PP1,PP2");
*aHostPort = (char *) malloc(hpsLen);
if (!*aHostPort)
return E_MEM;
memset(*aHostPort, 0, hpsLen);
sprintf(*aHostPort, "%d,%d,%d,%d,%d,%d",
(int)((char*)&servaddr.sin_addr)[0] & 0xFF,
(int)((char*)&servaddr.sin_addr)[1] & 0xFF,
(int)((char*)&servaddr.sin_addr)[2] & 0xFF,
(int)((char*)&servaddr.sin_addr)[3] & 0xFF,
(int)((char*)&servaddr.sin_port)[0] & 0xFF,
(int)((char*)&servaddr.sin_port)[1] & 0xFF);
return rv;
}
float
nsSocket::CalcRate(struct timeval *aPre, struct timeval *aPost, int aBytes)
{
float diffUsecs, rate;
/* param check */
if (!aPre || !aPost || aBytes <= 0)
return 0;
diffUsecs = (float)(aPost->tv_sec - aPre->tv_sec) * kUsecsPerSec;
diffUsecs += (float)aPost->tv_usec - (float)aPre->tv_usec;
rate = ((float)(aBytes/kKilobyte))/
((float)(diffUsecs/kUsecsPerSec));
return rate;
}
#ifdef TEST_NSSOCKET
void
my_nprintf(char *buf, int len)
{
printf("buf size = %d\n", len);
for (int i = 0; i < len; ++i)
{
printf("%c", *(buf+i));
}
printf("\n");
}
const int kTestBufSize = 1024;
int
main(int argc, char **argv)
{
DUMP(("*** %s: A self-test for nsSocket.\n", argv[0]));
if (argc < 4)
{
fprintf(stderr, "usage: %s <host> <port> <http_url>\n",
argv[0]);
exit(1);
}
int rv = nsSocket::OK;
nsSocket *sock = new nsSocket(argv[1], atoi(argv[2]));
char buf[kTestBufSize];
int bufSize;
memset(buf, 0, kTestBufSize);
// open socket
rv = sock->Open();
DUMP(("nsSocket::Open returned: %d\n", rv));
// prepare http request str
sprintf(buf, "GET %s HTTP/1.1\r\n\r\n", argv[3]);
bufSize = strlen(buf) + 1; // add 1 for NULL termination
// make request
rv = sock->Send((unsigned char *)buf, &bufSize);
DUMP(("nsSocket::Send returned: %d\t and sent: %d bytes\n", rv, bufSize));
// get response
do {
// prepare response buf
memset(buf, 0, kTestBufSize);
bufSize = kTestBufSize;
rv = sock->Recv((unsigned char *)buf, &bufSize);
DUMP(("nsSocket::Recv returned: %d\t and recd: %d bytes\n",
rv, bufSize));
// DUMP(("%s\n", buf));
my_nprintf(buf, bufSize);
} while (rv == nsSocket::E_READ_MORE);
// close socket
rv = sock->Close();
DUMP(("nsSocket::Close returned: %d\n", rv));
return 0;
}
#endif /* TEST_NSSOCKET */

Просмотреть файл

@ -0,0 +1,112 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#ifndef _NS_SOCKET_H_
#define _NS_SOCKET_H_
#ifndef _WINDOWS
#include <sys/time.h>
#endif
class nsSocket
{
public:
nsSocket(char *aHost, int aPort);
~nsSocket();
//----------------------------------------------------------------------
// Errors
//----------------------------------------------------------------------
enum
{
OK = 0,
E_PARAM = -1001,
E_MEM = -1002,
E_INVALID_HOST = -1003,
E_SOCK_OPEN = -1004,
E_SOCK_CLOSE = -1005,
E_TIMEOUT = -1006,
E_WRITE = -1007,
E_READ_MORE = -1008,
E_READ = -1009,
E_SMALL_BUF = -1010,
E_EOF_FOUND = -1011,
E_BIND = -1012,
E_LISTEN = -1014,
E_ACCEPT = -1015,
E_GETSOCKNAME = -1016,
E_WINSOCK = -1017
};
//----------------------------------------------------------------------
// Public interface
//----------------------------------------------------------------------
int Open();
int SrvOpen(); // server alternate to client Open()
int SrvAccept(); // must be called after SrvOpen()
int Send(unsigned char *aBuf, int *aBufSize);
int Recv(unsigned char *aBuf, int *aBufSize);
int Close();
int GetHostPortString(char **aHostPort);
static
float CalcRate(struct timeval *aPre, struct timeval *aPost, int aBytes);
private:
char *mHost;
int mPort;
int mFd; // connected socket
int mListenFd; // listening socket (only if SrvOpen() was called)
};
//----------------------------------------------------------------------
// Macro definitions
//----------------------------------------------------------------------
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL ((void *) 0L)
#endif
#ifdef DUMP
#undef DUMP
#endif
#if defined(DEBUG) || defined(DEBUG_sgehani)
#define DUMP(_vargs) \
do { \
printf("%s %d: ", __FILE__, __LINE__); \
printf _vargs; \
} while (0);
#else
#define DUMP(_vargs)
#endif
#endif /* _NS_SOCKET_H_ */

Просмотреть файл

@ -0,0 +1,40 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VAPTH = @srcdir@
include $(DEPTH)/config/autoconf.mk
CPPSRCS = TestLibxpnet.cpp
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
LIBS = -lxpnet_s
include $(topsrcdir)/config/rules.mk
INCLUDES += -I$(srcdir)/../src

Просмотреть файл

@ -0,0 +1,158 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Samir Gehani <sgehani@netscape.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nsFTPConn.h"
#include "nsHTTPConn.h"
const int kProxySrvrLen = 1024;
const char kHTTP[8] = "http://";
const char kFTP[7] = "ftp://";
const char kLoclFile[7] = "zzzFTP";
int
ProgressCB(int aBytesSoFar, int aTotalFinalSize)
{
printf(".");
return 0;
}
void
spew(char *funcName, int rv)
{
printf("%s returned %d\n", funcName, rv);
}
void
usage(char *prog)
{
fprintf(stderr, "usage: %s <URL> [ProxyServer ", prog);
fprintf(stderr, "ProxyPort [ProxyUserName ProxyPassword]\n");
}
int
main(int argc, char **argv)
{
char *proxyUser = 0, *proxyPswd = 0;
char proxyURL[kProxySrvrLen];
int rv = 0;
if (argc < 2)
{
usage(argv[0]);
exit(1);
}
/* has a proxy server been specified? */
if (argc >= 4)
{
memset(proxyURL, 0, kProxySrvrLen);
sprintf(proxyURL, "http://%s:%s", argv[2], argv[3]);
if (argc >=6)
{
proxyUser = argv[4];
proxyPswd = argv[5];
}
nsHTTPConn *conn = new nsHTTPConn(proxyURL);
conn->SetProxyInfo(argv[1], proxyUser, proxyPswd);
printf("Proxy URL: %s\n", argv[1]);
if (proxyUser && proxyPswd)
{
printf("Proxy User: %s\n", proxyUser);
printf("Proxy Pswd: %s\n", proxyPswd);
}
rv = conn->Open();
spew("nsHTTPConn::Open", rv);
rv = conn->Get(ProgressCB, NULL); // use leaf from URL
printf("\n"); // newline after progress completes
spew("nsHTTPConn::Get", rv);
rv = conn->Close();
spew("nsHTTPConn::Close", rv);
}
else
{
/* is this an HTTP URL? */
if (strncmp(argv[1], kHTTP, strlen(kHTTP)) == 0)
{
nsHTTPConn *conn = new nsHTTPConn(argv[1]);
rv = conn->Open();
spew("nsHTTPConn::Open", rv);
rv = conn->Get(ProgressCB, NULL);
printf("\n"); // newline after progress completes
spew("nsHTTPConn::Get", rv);
rv = conn->Close();
spew("nsHTTPConn::Close", rv);
}
/* or is this an FTP URL? */
else if (strncmp(argv[1], kFTP, strlen(kFTP)) == 0)
{
char *host = 0, *path = 0, *file = (char*) kLoclFile;
int port = 21;
rv = nsHTTPConn::ParseURL(kFTP, argv[1], &host, &port, &path);
spew("nsHTTPConn::ParseURL", rv);
nsFTPConn *conn = new nsFTPConn(host);
rv = conn->Open();
spew("nsFTPConn::Open", rv);
if (strrchr(path, '/') != (path + strlen(path)))
file = strrchr(path, '/') + 1; // set to leaf name
rv = conn->Get(path, file, nsFTPConn::BINARY, 1, ProgressCB);
printf("\n"); // newline after progress completes
spew("nsFTPConn::Get", rv);
rv = conn->Close();
spew("nsFTPConn::Close", rv);
if (host)
free(host);
if (path)
free(path);
}
/* or we don't understand the args */
else
{
fprintf(stderr, "Like, uhm, dude! I don't get you. ");
fprintf(stderr, "See usage...\n");
usage(argv[0]);
}
}
return 0;
}

Просмотреть файл

@ -0,0 +1,49 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator client code,
# released March 31, 1998.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Samir Gehani <sgehani@netscape.com>
#
MODULE=xpnet
DEPTH=..\..\..\..
MAKE_OBJ_TYPE=EXE
EXENAME=TestLibxpnet
PDBFILE=TestLibxpnet
MAPFILE=TestLibxpnet.map
PROGRAM=.\$(OBJDIR)\$(EXENAME).exe
OBJS=.\$(OBJDIR)\TestLibxpnet.obj
LINCS=-I..\src
LLIBS=$(DIST)\lib\$(MODULE)_s.lib
include <$(DEPTH)/config/rules.mak>
install:: $(PROGRAM)
$(MAKE_INSTALL) $(PROGRAM) $(DIST)\bin
clobber::
$(RM) $(DIST)\bin\$(EXENAME).exe