blob: 1990f71969e284bc5db0e18552abfe8c2b31ef38 [file] [log] [blame]
#include <string.h>
#include <stdlib.h>
#ifdef UEMF
#include "uemf.h"
#else
#include <socket.h>
#include <types.h>
#include <unistd.h>
#include "emfInternal.h"
#endif
static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode);
static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
struct sockaddr *server);
int socketHighestFd = -1;
socket_t **socketList;
int socketMax;
int socketWriteString(int sid, char_t *buf)
{
#ifdef UNICODE
char *byteBuf;
int r, buf_len;
buf_len = gstrlen(buf);
byteBuf = ballocUniToAsc(buf, buf_len);
r = socketWrite(sid, byteBuf, buf_len);
bfreeSafe(B_L, byteBuf);
return r;
#else
return socketWrite(sid, buf, strlen(buf));
#endif /* UNICODE */
}
int socketWrite(int sid, char *buf, int bufsize)
{
socket_t *sp;
ringq_t *rq;
int buf_len, bytesWritten, room;
a_assert(buf);
a_assert(bufsize >= 0);
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
rq = &sp->outBuf;
for (bytesWritten = 0; bufsize > 0; ) {
if ((room = ringqPutBlkMax(rq)) == 0) {
if (socketFlush(sid) < 0) {
return -1;
}
if ((room = ringqPutBlkMax(rq)) == 0) {
if (sp->flags & SOCKET_BLOCK) {
#if (defined (WIN) || defined (CE))
int errCode;
if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE, &errCode)) {
return -1;
}
#endif
continue;
}
break;
}
continue;
}
buf_len = min(room, bufsize);
ringqPutBlk(rq, (unsigned char *) buf, buf_len);
bytesWritten += buf_len;
bufsize -= buf_len;
buf += buf_len;
}
return bytesWritten;
}
int socketRead(int sid, char *buf, int bufsize)
{
socket_t *sp;
ringq_t *rq;
int buf_len, room, errCode, bytesRead;
a_assert(buf);
a_assert(bufsize > 0);
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
if (sp->flags & SOCKET_EOF) {
return 0;
}
rq = &sp->inBuf;
for (bytesRead = 0; bufsize > 0; ) {
buf_len = min(ringqLen(rq), bufsize);
if (buf_len <= 0) {
if ((sp->flags & SOCKET_BLOCK) &&
(bytesRead > 0)) {
break;
}
ringqFlush(rq);
room = ringqPutBlkMax(rq);
buf_len = socketGetInput(sid, (char *) rq->endp, room, &errCode);
if (buf_len < 0) {
if (errCode == EWOULDBLOCK) {
if ((sp->flags & SOCKET_BLOCK) &&
(bytesRead == 0)) {
continue;
}
// if (bytesRead >= 0) { // kw 3 ; bytesRead>=0 always be true
return bytesRead;
// }
}
return -1;
} else if (buf_len == 0) {
if (bytesRead == 0) {
sp->flags |= SOCKET_EOF;
}
return bytesRead;
}
ringqPutBlkAdj(rq, buf_len);
buf_len = min(buf_len, bufsize);
}
memcpy(&buf[bytesRead], rq->servp, buf_len);
ringqGetBlkAdj(rq, buf_len);
bufsize -= buf_len;
bytesRead += buf_len;
}
return bytesRead;
}
int socketFlush(int sid)
{
socket_t *sp;
ringq_t *rq;
int rq_len, bytesWritten, errCode;
int errEINTRNum = 0; /* myp: ÓÃÓÚ¹æ±Üsocket´íÎó */
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
rq = &sp->outBuf;
if (! (sp->flags & SOCKET_BLOCK)) {
sp->flags |= SOCKET_FLUSHING;
}
while (ringqLen(rq) > 0) {
rq_len = ringqGetBlkMax(&sp->outBuf);
bytesWritten = socketDoOutput(sp, (char*) rq->servp, rq_len, &errCode);
if (bytesWritten < 0) {
if (errCode == EINTR && errEINTRNum++ < 1000) {
continue;
// } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) { kw 3 // #define EWOULDBLOCK EAGAIN
} else if (errCode == EAGAIN) {
if (sp->saveMask < 0 ) {
sp->saveMask = sp->handlerMask;
socketRegisterInterest(sp,
sp->handlerMask | SOCKET_WRITABLE);
}
return 0;
}
return -1;
}
ringqGetBlkAdj(rq, bytesWritten);
}
if (ringqLen(rq) == 0) {
ringqFlush(rq);
}
if (sp->saveMask >= 0) {
socketRegisterInterest(sp, sp->saveMask);
sp->saveMask = -1;
}
sp->flags &= ~SOCKET_FLUSHING;
return 0;
}
int socketGets(int sid, char_t **buf)
{
socket_t *sp;
ringq_t *lq;
char c = '\0'; //cov
int rc, rq_len;
a_assert(buf);
*buf = NULL;
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
lq = &sp->lineBuf;
while (ringqLen(lq) < 1536) {
if ((rc = socketRead(sid, &c, 1)) < 0) {
return rc;
}
if (rc == 0) {
if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
c = '\n';
} else {
return -1;
}
}
if (c == '\n') {
rq_len = ringqLen(lq);
if (rq_len > 0) {
*buf = ballocAscToUni((char *)lq->servp, rq_len);
} else {
*buf = NULL;
}
ringqFlush(lq);
return rq_len;
} else if (c == '\r') {
continue;
}
ringqPutcA(lq, c);
}
ringqFlush(lq);
return -1;
}
int socketInputBuffered(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
if (socketEof(sid)) {
return -1;
}
return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
}
int socketEof(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
return sp->flags & SOCKET_EOF;
}
void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler,
int data)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return;
}
sp->handler = handler;
sp->handler_data = data;
socketRegisterInterest(sp, handlerMask);
}
static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode)
{
struct sockaddr_in server;
int bytes;
a_assert(sp);
a_assert(buf);
a_assert(toWrite > 0);
a_assert(errCode);
*errCode = 0;
if (sp->flags & SOCKET_BROADCAST) {
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_BROADCAST;
server.sin_port = htons((short)(sp->port & 0xFFFF));
bytes = sendto(sp->sock, buf, toWrite, 0,(struct sockaddr *) &server, sizeof(server));
} else if (sp->flags & SOCKET_DATAGRAM) {
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(sp->host);
server.sin_port = htons((short)(sp->port & 0xFFFF));
bytes = sendto(sp->sock, buf, toWrite, 0,(struct sockaddr *) &server, sizeof(server));
} else {
bytes = send(sp->sock, buf, toWrite, 0);
}
if (bytes < 0) {
*errCode = socketGetError();
//printf("\n socketDoOutput ERROR: bytes = %d, *errCode = %d! ", bytes, *errCode);
return -1;
} else if (bytes == 0 && bytes != toWrite) {
*errCode = EWOULDBLOCK;
//printf("\n socketDoOutput ERROR: bytes = %d, *errCode = %d! ", bytes, *errCode);
return -1;
}
return bytes;
}
void socketDeleteHandler(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return;
}
sp->handler = NULL;
socketRegisterInterest(sp, 0);
}
int socketAlloc(char *host, int port, socketAccept_t accept, int flags)
{
socket_t *sp;
int sid;
if ((sid = hAllocEntry((void***) &socketList, &socketMax,
sizeof(socket_t))) < 0) {
return -1;
}
sp = socketList[sid];
sp->sid = sid;
sp->accept = accept;
sp->port = port;
sp->fileHandle = -1;
sp->saveMask = -1;
if (host) {
strncpy(sp->host, host, sizeof(sp->host)-1);
}
a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK|
SOCKET_LISTENING)) == 0);
sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK|
SOCKET_LISTENING);
ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1);
ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
return sid;
}
void socketFree(int sid)
{
socket_t *sp;
char_t buf[256];
int i;
int recv_len = -1;
if ((sp = socketPtr(sid)) == NULL) {
return;
}
socketRegisterInterest(sp, 0);
if (sp->sock >= 0) {
socketSetBlock(sid, 0);
if (shutdown(sp->sock, 1) >= 0) {
recv_len = recv(sp->sock, buf, sizeof(buf), 0);
if(recv_len < 0){
;
}else if(recv_len == 0){
// ÕâÀï±íʾ¶Ô¶ËµÄsocketÒÑÕý³£¹Ø±Õ?
;
}else if(recv_len == sizeof(buf)){
;
}else{
;// ÐèÒªÔٴζÁÈ¡
}
}
#if (defined (WIN) || defined (CE))
closesocket(sp->sock);
#else
close(sp->sock);
#endif
}
ringqClose(&sp->inBuf);
ringqClose(&sp->outBuf);
ringqClose(&sp->lineBuf);
bfree(B_L, sp);
socketMax = hFree((void***) &socketList, sid);
socketHighestFd = -1;
for (i = 0; i < socketMax; i++) {
if ((sp = socketList[i]) == NULL) {
continue;
}
socketHighestFd = max(socketHighestFd, sp->sock);
}
}
int socketGetError()
{
#if (defined (WIN) || defined (CE))
switch (WSAGetLastError()) {
case WSAEWOULDBLOCK:
return EWOULDBLOCK;
case WSAECONNRESET:
return ECONNRESET;
case WSAENETDOWN:
return ENETDOWN;
case WSAEPROCLIM:
return EAGAIN;
case WSAEINTR:
return EINTR;
default:
return EINVAL;
}
#else
return errno;
#endif
}
socket_t *socketPtr(int sid)
{
if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
a_assert(NULL);
errno = EBADF;
return NULL;
}
a_assert(socketList[sid]);
return socketList[sid];
}
int socketGetHandle(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
return sp->sock;
}
int socketGetBlock(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
a_assert(0);
return 0;
}
return (sp->flags & SOCKET_BLOCK);
}
int socketGetMode(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
a_assert(0);
return 0;
}
return sp->flags;
}
void socketSetMode(int sid, int mode)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
a_assert(0);
return;
}
sp->flags = mode;
}
int socketGetPort(int sid)
{
socket_t *sp;
if ((sp = socketPtr(sid)) == NULL) {
return -1;
}
return sp->port;
}