This is a multi-part message in MIME format.
------=_NextPart_000_0029_01C7778A.632E0120
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_002A_01C7778A.632E0120"
------=_NextPart_001_002A_01C7778A.632E0120
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Hi all,
I need a C programmer to help me out convert the single file attached to =
either VB.NET or VFP. =20
Does anybody know any C programmer that can do this kind of conversion?
Thanks!
--=20
Edhy Rijo
www.progytech.com
Bronx NY
------=_NextPart_001_002A_01C7778A.632E0120
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.6000.16397" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT size=3D2>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT=20
face=3DCalibri>Hi all,</FONT></FONT></P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT face=3DCalibri=20
size=3D3></FONT> </P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT =
face=3DCalibri>I=20
need a C programmer to help me out convert the single file attached to =
either=20
VB.NET or VFP.<SPAN style=3D"mso-spacerun: yes"> =
</SPAN></FONT></FONT></P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT=20
face=3DCalibri><SPAN style=3D"mso-spacerun: =
yes"></SPAN></FONT></FONT> </P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT=20
face=3DCalibri><SPAN style=3D"mso-spacerun: yes"></SPAN>Does =
anybody know any C=20
programmer that can do this kind of conversion?</FONT></FONT></P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT=20
face=3DCalibri></FONT></FONT> </P>
<P class=3DMsoNormal style=3D"MARGIN: 0in 0in 0pt"><FONT size=3D3><FONT=20
face=3DCalibri>Thanks!<?xml:namespace prefix =3D o ns =3D=20
"urn:schemas-microsoft-com:office:office"=20
/><o:p></o:p></FONT></FONT></P></FONT></DIV><FONT size=3D2>
<DIV><BR>-- <BR>Edhy Rijo<BR><A=20
href=3D"http://www.progytech.com">www.progytech.com</A><BR>Bronx =
NY</DIV>
<DIV> </DIV>
<DIV></FONT> </DIV></BODY></HTML>
------=_NextPart_001_002A_01C7778A.632E0120--
------=_NextPart_000_0029_01C7778A.632E0120
Content-Type: text/plain;
name="Source.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="Source.txt"
*
* $Id$=20
* $Source$
*/
/*
* CDRSrv.c
*
* CDR Server code for Multithreading Applications in Win32
* This server can only be run on Windows NT,
* version 3.51 or later. The client will be a Gateway
* which will be configured with cdrserverport as 9002 and=20
* cdrserverip as the CDR Server PC's IP Address.=20
* For each Gateway, it will create a yymmdd_xxx_xxx_xxx_xxx.cdr file.
* where yymmdd is the year, month, and day, xxx_xxx_xxx_xxx generated
* from the CDR Server PC ip address by replacing '.' with '_'.
* Before running this program, a Gateway administrator has to=20
* config the Gateway by the following steps:
*=20
* 1. Telnet <gateway ip address>
* 2. <company>> Password: <Gateway login password>
* <company> Thank you. Type ? for help
* 3 <company> con sys cdrpassword <your cdr password>=20
* 4. <company> con sys cdrserverip 1 <your pc ip address>
* 5. <company> con sys cdrserverport 1 9002
* 6. <company> con sub
* 7. <company> exit
* 8. You should create a cdrserver.cfg text file using notepad or =
textpad
* to contain the following threelines:
* cdr_password <your cdr password>
* max_chassis_no <number of gateways that you want to connect>
* max_cdr_per_file <number of cdr record per cdr file>
* 9. Enter cdrsrv <-f cfgfile_path\cdrserver.cfg> <-o cdrfile_path> =
<-p cdrserverport> <-v ?>
*=20
* 10. Output: all the cdr files will be in <cdrfile_path>\ directory
*=20
*/
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>
#include <string.h>
#include <winsock.h>
#include <io.h>
#include <direct.h>
#include <time.h>
//#include "MtVerify.h"
// Pick a port number that seems to be away from all others
#define MAX_CONNECTION_NUM 100
#define MAX_REC_LEN 512
#define DATE_LEN 7
#define IPADDR_LEN 16
#define PORT_LEN 7
#define VERSION_LEN 11
#define MAX_NAME_LEN 32
#define MAX_CHASSIS_NUM 100
#define MAX_FILE_NAME_LEN 128
#define MAX_PATH_LEN 256
#define MAX_ESQN_LEN 10
#define MAX_PASSWORD_LEN 16
#define MAX_CDR_NUM 10000
#define MAX_RESETNUM_LEN 11
#define MAX_FILE_INDEX_LEN 4
// States of the CDR Server=20
#define AVAIL -1
#define START 0
#define WELCOMED 1
#define CONNECTED 2
#define PASSWORDSENT 3
#define PASSWORDOK 4
#define GOTGWIP 5
#define GOTUNITNAME 6
#define GOTLASTSEQNO 7
#define READY 8
//
// Structure definition
//
// The context key keeps track of how the I/O
// is progressing for each individual file handle.
struct ContextKey
{
SOCKET sock;
// Input
char InBuffer[MAX_REC_LEN];
OVERLAPPED ovIn;
// Output
int nCDRBuffIndex;
int nOutBuffIndex;
char CDRBuffer[MAX_REC_LEN];
char OutBuffer[MAX_REC_LEN];
OVERLAPPED ovOut;
DWORD dwWritten;
int sid;
};
//
// Global variables
//
struct ContextKey *pCntx[MAX_CONNECTION_NUM];
HANDLE ghFile;
HANDLE ghCompletionPort[MAX_CONNECTION_NUM];
HANDLE hFile[MAX_CONNECTION_NUM];
OVERLAPPED overlap[MAX_CONNECTION_NUM];
char cdrfile_path[MAX_PATH_LEN];
char cdrpassword[MAX_PASSWORD_LEN];
char cdrport[PORT_LEN];
char cfgfile_path[MAX_PATH_LEN];
char version[VERSION_LEN];
int cid; //Current Connection Identifier
int state[MAX_CONNECTION_NUM];
int maxchano =3D MAX_CHASSIS_NUM;=20
int maxcdrno =3D MAX_CDR_NUM;
short cdrserverport;
typedef struct chassis {
short avail;
char IpAddr[IPADDR_LEN];
char unitname[MAX_NAME_LEN];
char resetnum[MAX_RESETNUM_LEN];
long resetno;
long curr_resetno;=20
} CHASSIS;
CHASSIS cha[MAX_CHASSIS_NUM];=09
//
// Functions
//
void CreateWorkerThreads(int sid);
DWORD WINAPI ThreadFunc(LPVOID sid);
int IssueRead(struct ContextKey *pCntx);
int convert_cdr(struct ContextKey *pCntx);
void CheckOsVersion();
void FatalError(char *s);
void GetConfigInfo(char *pswd, int *maxchano, int *maxcdrno);
///////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
=20
SOCKET listener;
SOCKET AcceptSocket;
WSADATA WsaData;
struct sockaddr_in serverAddress;
struct sockaddr_in clientAddress;
int clientAddressLength;
int err;
int i =3D 0;
struct ContextKey *pKey[MAX_CONNECTION_NUM];
char *curr_path;
char ver[VERSION_LEN];
=09
// Initialize cdrip to 9002 as the default value
// the cfg file path and cdr file path to the working directory path
strcpy(version, "07.22.2002_V1.0.3");
strcpy(cdrport, "9002");
curr_path =3D _getcwd(NULL, MAX_PATH_LEN);
strcpy(cfgfile_path, curr_path);
strcat(cfgfile_path, "\\cdrserver.cfg");=09
strcpy(cdrfile_path, curr_path);
strcat(cdrfile_path, "\\");
strcpy(cdrpassword, "quintum");
printf("cfgfile_path =3D %s, cdrfile_path =3D %s\n", cfgfile_path, =
cdrfile_path);
free(curr_path);
//
// parse the command options
//
if (argc%2 !=3D 1)=20
{=20
fprintf(stdout, "Usage: %s -f <cfgfile_path>\\cdrserver.cfg -o =
<cdrfile_path> -p <port#> <-v ?>\n", argv[0]);
return -1;
}
else {
for (i =3D 1; i < argc;i=3Di+2) {
//
// Get cdrserver.cfg path
//
if (strcmpi(argv[i], "-f") =3D=3D 0) {=09
strcpy (cfgfile_path, argv[i+1]);
// fprintf(stdout, "CFG FILE PATH =3D %s\n", cfgfile_path);
}
else if (strcmpi(argv[i], "-o") =3D=3D 0) {
strcpy (cdrfile_path, argv[i+1]);
strcat (cdrfile_path, "\\");
// fprintf(stdout, "CDR FILE PATH =3D %s\n", cdrfile_path);
}
else if (strcmpi(argv[i], "-p") =3D=3D 0) {
strcpy (cdrport, argv[i+1]);
// fprintf(stdout, "CDR PORT =3D %s\n", cdrport);
}
else if (strcmpi(argv[i], "-v") =3D=3D 0) {
strncpy (ver, argv[i+1], VERSION_LEN-1);
strcat(ver, "\0");
if (strcmpi(ver, "?") =3D=3D 0) {
fprintf(stdout, "cdr server version =3D %s\n", version);
} else {
fprintf(stdout, "cdr server version =3D %s\n", version);
}
}
else=20
fprintf(stdout, "Usage: %s -f <cfgfile_path>\\cdrserver.cfg\n -o =
<cdrfile_path> -p <port#> <-v ?>\n", argv[0]);
}
}
cdrserverport =3D atoi(cdrport); // convert cdr tcp ip port number =
into integer=20
// fprintf(stdout, "TCP IP PORT =3D %d\n", cdrserverport);
//
// Now we are ready to open the cdrserver.cfg file to get the cdr =
password,
// the maximum number of gateways that it will collect CDRs from,=20
// the maximum records that each cdr file can contain.
//
ghFile =3D CreateFile(
cfgfile_path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (ghFile =3D=3D INVALID_HANDLE_VALUE)
{
FatalError("Open Cdrserver Configuration File Failed\n");
}
else=20
{
GetConfigInfo(&(cdrpassword[0]), &maxchano, &maxcdrno);
}
fprintf(stdout, "Maximal Number of CDRs per file =3D %d\n", maxcdrno);
/* Initialize the Chassis Units */
for (i=3D0; i < MAX_CHASSIS_NUM; i++) {
=09
strcpy(cha[i].IpAddr, "0.0.0.0\0");
strcpy(cha[i].unitname, "unit1\0");
strcpy(cha[i].resetnum, "-1\0");
cha[i].curr_resetno =3D -1;
cha[i].resetno =3D -1;
cha[i].avail =3D 1;
}
CheckOsVersion();
err =3D WSAStartup (0x0101, &WsaData);
if (err =3D=3D SOCKET_ERROR)
{
FatalError("WSAStartup Failed");
return EXIT_FAILURE;
}
/*
* Open a TCP socket connection to the server
* By default, a socket is always opened
* for overlapped I/O. Do NOT attach this
* socket (listener) to the I/O completion
* port!
*/
listener =3D socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0)
{
FatalError("socket() failed");
return EXIT_FAILURE;
}
// set socket option to so_keepalive=20
/*
* Bind our local address
*/
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family =3D AF_INET;
serverAddress.sin_addr.s_addr =3D htonl(INADDR_ANY);
serverAddress.sin_port =3D htons(cdrserverport);
err =3D bind(listener,
(struct sockaddr *)&serverAddress,
sizeof(serverAddress)
);
if (err < 0) {
FatalError("bind() failed");
} else {
int keepalivestat =3D 1;=20
setsockopt(listener,=20
IPPROTO_TCP,=20
SO_KEEPALIVE,=20
(char *)&keepalivestat,=20
sizeof(int));
// sendto(listener,=20
// (char *)&SAPData,=20
// sizeof(SAPData),=20
// MSG_DONTROUTE,
// (struct sockaddr *)&serverAddress,
// sizeof(serverAddress));
// Set timer to remind us to send SAP packet every 60 seconds.
// SetTimer(hwnd, SAPTIMER, 60000, NULL);
}
//
// Create a IO completion port for each incoming gateway connection
//=20
for (i =3D 0; i < MAX_CONNECTION_NUM; i++) {
ghCompletionPort[i] =3D CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL, // No prior port
0, // No key
0 // Use default # of threads
);
if (ghCompletionPort[i] =3D=3D NULL)
FatalError("CreateIoCompletionPort() failed");
CreateWorkerThreads(i);
state[i] =3D AVAIL;
}
listen(listener, 10);
fprintf(stderr, "CDR Server with I/O Completion Ports\n");
fprintf(stderr, "Running on TCP port %d\n", cdrserverport);
fprintf(stderr, "\nPress Ctrl+C to stop the server\n");
//
// Loop forever accepting requests new connections
// and starting reading from them.
//
cid =3D -1;
for (;;)
{
=09
clientAddressLength =3D sizeof(clientAddress);
AcceptSocket =3D accept(listener,
(struct sockaddr *)&clientAddress,
&clientAddressLength);
if (AcceptSocket < 0)
{
FatalError("accept() Failed");
return EXIT_FAILURE;
}
for (i=3D0; i < MAX_CONNECTION_NUM; i++) {
if (state [i] =3D=3D AVAIL) {=20
cid =3D i;
printf("AVAIL CONN ID =3D %d\n", cid);
break;
}
}
if (cid =3D=3D -1)
FatalError("NO AVAILABLE TCP/IP Connections");
pKey[cid] =3D calloc(1, sizeof(struct ContextKey));
pKey[cid]->sock =3D AcceptSocket;
pKey[cid]->ovOut.hEvent =3D CreateEvent(NULL, TRUE, FALSE, =
NULL);
// Set the event for writing so that packets
// will not be sent to the completion port when
// a write finishes.
pKey[cid]->ovOut.hEvent =3D =
(HANDLE)((DWORD)pKey[cid]->ovOut.hEvent | 0x1);
pKey[cid]->sid =3D cid;
// Associate the socket with the completion port
CreateIoCompletionPort(
(HANDLE)AcceptSocket,
ghCompletionPort[cid],
(DWORD)pKey[cid], // No key
0 // Use default # of threads
);
// Kick off the first read
state[cid] =3D START;
if (IssueRead(pKey[cid]) < 0)=20
{
free(pKey[cid]);
state[cid] =3D AVAIL;
fprintf(stderr, "CONNID =3D %d, IssueRead Failed\n", cid);
}
=09
=09
}
return 0;
}
void CreateWorkerThreads(int sid)
{
SYSTEM_INFO sysinfo;
DWORD dwThreadId;
DWORD dwThreads;
DWORD i;
GetSystemInfo(&sysinfo);
dwThreads =3D sysinfo.dwNumberOfProcessors * 2 + 2;
for (i=3D0; i<dwThreads; i++)
{
HANDLE hThread;
hThread =3D CreateThread(
NULL, 0, ThreadFunc, (LPVOID)sid, 0, &dwThreadId
);
CloseHandle(hThread);
}
}
//
// Each worker thread starts here.
DWORD WINAPI ThreadFunc(LPVOID id)
{
BOOL bResult;
DWORD dwNumRead;
char path[MAX_PATH_LEN];
=09
LPOVERLAPPED lpOverlapped;
int i, j, k;
int uendidx;
int cha_idx;
int recno =3D 0;
int dailyfilecount =3D 0;
int fret;
int retry =3D 3;
long lsqno =3D 0; // the largest sequnce number
long csqno =3D 0; // the current record's sequence number
long esqno =3D0 ; // the expected next sequence number
=09
BOOL rc;
char c;
char seqno[MAX_ESQN_LEN];
char lastseqno[MAX_ESQN_LEN];
char cdrecord[MAX_REC_LEN], record[MAX_REC_LEN];
char cdrfilename[MAX_FILE_NAME_LEN];
char currdate[DATE_LEN];
char ipaddr[IPADDR_LEN];
char cdrdir[IPADDR_LEN];
char dailyfileindex[MAX_FILE_INDEX_LEN];
time_t timer;
struct tm *today;=20
DWORD numread;
=09
k =3D (int) id;
//
// Loop forever on getting packets from
// the I/O completion port.
//
for (;;)
{
bResult =3D GetQueuedCompletionStatus(
ghCompletionPort[k],
&dwNumRead,
&(DWORD)(pCntx[k]),
&lpOverlapped,
INFINITE
);
if (bResult =3D=3D FALSE
&& lpOverlapped =3D=3D NULL)
{
FatalError(
"ThreadFunc - Illegal call to =
GetQueuedCompletionStatus");
}
else if (bResult =3D=3D FALSE
&& lpOverlapped !=3D NULL)
{
// This happens occasionally instead of
// end-of-file. Not sure why.
closesocket(pCntx[k]->sock);
free(pCntx[k]);
state[k] =3D AVAIL; // set the connection to be available again
fprintf(stderr,"ThreadFunc - I/O operation failed, CONN ID =
=3D %d\n", k);
}
else if (dwNumRead =3D=3D 0)
{
closesocket(pCntx[k]->sock);
free(pCntx[k]);
CloseHandle(hFile[k]); // close the cdr record file too
state[k] =3D AVAIL; // set the connection to be available again
fprintf(stderr, "ThreadFunc - End of file. CONN ID =3D =
%d\n", k);
}
//=20
// Save each incoming record in the CDRbuffer
// Process the incoming CDR according to it current=20
// state
// Each thread is running a finite state machine
// There are totally 9 different states
// Index k represent the current connection session id.
//
=20
else
{
// Figure out where in the buffer to save the character
char *pch =3D =
&(pCntx[k]->CDRBuffer[pCntx[k]->nCDRBuffIndex++]);
*pch++ =3D pCntx[k]->InBuffer[0];
*pch =3D '\0'; // For debugging, WriteFile doesn't care
//fprintf(stdout, "InBuffer =3D %s, state[%d] =3D %d\n", =
pCntx[k]->InBuffer, k, state[k]);
switch (state[k]) {
case START:
if (pCntx[k]->InBuffer[0] =3D=3D '\n')
{
// Get Welcome string from the Gateway=20
// Break and goback to reac the incoming data block
c =3D pCntx[k]->CDRBuffer[0];
if ((c =3D=3D 'T') || (c =3D=3D 'H') || (c =3D=3D 'W'))
{
fprintf(stdout, "GET WELCOME STRING: CDRBuffer =3D %s\n", =
pCntx[k]->CDRBuffer);
state[k] =3D WELCOMED;
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
}
}
break;
case WELCOMED:
if (pCntx[k]->InBuffer[0] =3D=3D '\n')=20
{
if (pCntx[k]->CDRBuffer[0] =3D=3D 'C')
{
// Get Connect from IpAddr/Port# CDRSVRIpAddr/CDRPort to a gateway =
port message
// Break and go back to read next incoming data block
state[k] =3D CONNECTED;
fprintf(stdout, "CONNECTED: CDRBuffer =3D %s\n", =
pCntx[k]->CDRBuffer);
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
}
}
break;
case CONNECTED:
// If the last character read is a ':', then the data block is a=20
// "Password:" prompter
if (pCntx[k]->InBuffer[0] =3D=3D ':')=20
{=20
//copy the CDR password to the CDRBuffer and sent it back to the =
Gateway
// fprintf(stdout, "Get Password Prompt: CDRBuffer =3D %s\n", =
pCntx[k]->CDRBuffer);
//strncpy(&pCntx[k]->CDRBuffer[0], "ming\r\n",6);
for (i=3D0; i < MAX_PASSWORD_LEN; i++) {
if ( cdrpassword[i] !=3D '\0')=20
pCntx[k]->CDRBuffer[i] =3D cdrpassword[i];
else=20
break;
}
pCntx[k]->CDRBuffer[i++] =3D '\r';
pCntx[k]->CDRBuffer[i++] =3D '\n';
pCntx[k]->nCDRBuffIndex =3D i;
fprintf(stdout, "CONNECTED: Send Password %s back to Gateway, =
nOutBuffIndex =3D %d\n",=20
pCntx[k]->CDRBuffer, pCntx[k]->nCDRBuffIndex);
WriteFile
(
(HANDLE)(pCntx[k]->sock),
pCntx[k]->CDRBuffer,
pCntx[k]->nCDRBuffIndex,
&pCntx[k]->dwWritten,
&pCntx[k]->ovOut
);
state[k] =3D PASSWORDSENT;
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
}
break;=09
case PASSWORDSENT:
//
// If the last character read is a '\n', then=20
// it means that Gateway accepts the password that we just sent
//
if ((pCntx[k]->InBuffer[0] =3D=3D '\n') ||=20
(pCntx[k]->InBuffer[0] =3D=3D '\r') ||
(pCntx[k]->InBuffer[0] =3D=3D '\0'))=20
{
fprintf(stdout, "PASSWORDSENT: state =3D PASSWORD OK \n");
state[k] =3D PASSWORDOK;=09
}
if ( (pCntx[k]->InBuffer[0] =3D=3D 'P') || (pCntx[k]->InBuffer[0] =
=3D=3D 'S'))
{
fprintf(stdout, "PASSWORDSENT: CDRSRV Password Failure, Check CDR =
PASSWORD set in the Gateway\n");
// we will retry it again
state[k] =3D CONNECTED;
}
=20
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
case PASSWORDOK:
//
// If Password is OK, The Gateway will send its own IP address and =
end with a ','=20
//=20
=09
// fprintf(stdout, "PASSWORDOK: CDRBuffer =3D %s, =
pCntx[%d]->nCDRBuffIndex =3D %d\n",=20
// pCntx[k]->CDRBuffer, k, pCntx[k]->nCDRBuffIndex);
if ( (pCntx[k]->InBuffer[0] =3D=3D 'P') || (pCntx[k]->InBuffer[0] =
=3D=3D 'S'))
{
fprintf(stdout, "PASSWORDOK? CDRSRV Password Failure, Check CDR =
PASSWORD set in the Gateway\n");
// we will retry it again
state[k] =3D CONNECTED;
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
}
=09
//fprintf(stdout, "PASSWORDOK: pCntx[k]->InBuffer[0] =3D %c\n", =
pCntx[k]->InBuffer[0]); =09
if(pCntx[k]->InBuffer[0] =3D=3D ',')=20
{
// fprintf(stdout, "PASSWORDOK: CDRBuffer =3D %s, =
pCntx[%d]->nCDRBuffIndex =3D %d\n",=20
// pCntx[k]->CDRBuffer, k, pCntx[k]->nCDRBuffIndex);
j =3D 0;
for (i=3D0; i < pCntx[k]->nCDRBuffIndex; i++) {
c =3D pCntx[k]->CDRBuffer[i];
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
ipaddr[j++] =3D c;
break;
default:
break;
}
}
ipaddr[j] =3D '\0';
fprintf(stdout, "PASSWORDOK: Connecting to the Chassis with ipaddr =
=3D %s\n", ipaddr);=09
cha_idx =3D -1;
for (i=3D 0; i < MAX_CHASSIS_NUM; i++) {
if (strcmp(ipaddr, cha[i].IpAddr) =3D=3D 0) {
cha_idx =3D i;
fprintf(stdout, "PASSWORDOK: ipaddr =3D %s, cha[%d].IpAddr =3D =
%s\n", ipaddr, i, cha[i].IpAddr);
break;
}
}
// if it cannot find a chassis with the ip address, then
// find the first available chassis slot to store the chassis =
information
// fprintf(stdout, "PASSWORDOK: cha_idx =3D %d\n", cha_idx);
if (cha_idx =3D=3D -1) {
for (i=3D 0; i < MAX_CHASSIS_NUM; i++) {
if ( cha[i].avail =3D=3D 1) {
cha_idx =3D i;
strcpy(cha[cha_idx].IpAddr, ipaddr);
cha[cha_idx].avail =3D 0;=20
// fprintf(stdout, "PASSWORDOK: ipaddr =3D %s, Got %dth Chassis =
IP %s\n", ipaddr, cha_idx, cha[cha_idx].IpAddr);=09
break;
}
}
}
if (cha_idx =3D=3D -1) {
fprintf(stdout, "ERROR: Too Many Chassises, Capacity Overflow\n");
return -1;
}
fprintf(stdout, "PASSWORDOK: GET %dth Chassis IP %s\n",cha_idx, =
cha[cha_idx].IpAddr);=09
state[k] =3D GOTGWIP;
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;=20
}
break;
case GOTGWIP:
uendidx =3D 0;
//
// After getting the Gateway IP Address, it sends its own unit name =
and followed by a newline char
//
// fprintf(stdout, "GOTGWIP: INBuffer =3D %c, state[k] =3D %d\n", =
pCntx[k]->InBuffer[0], state[k]);
if ((pCntx[k]->InBuffer[0] =3D=3D '\n') || (pCntx[k]->InBuffer[0] =
=3D=3D '\r'))
{
=09
// fprintf(stdout, "GOTGWIP: CDRBuffer =3D %s, state[%d] =3D %d\n", =
pCntx[k]->CDRBuffer, k, state[k]);
j =3D 0;
for (i=3D0; i < pCntx[k]->nCDRBuffIndex; i++)
{
c =3D pCntx[k]->CDRBuffer[i];
if ((c !=3D ',') && (c !=3D '\r') && (c !=3D '\n')) {
if (uendidx =3D=3D 0)=20
cha[cha_idx].unitname[j++] =3D c;
else=20
cha[cha_idx].resetnum[j++] =3D c;
}
else if ( c =3D=3D ',') {
cha[cha_idx].unitname[j] =3D '\0';
uendidx =3D j;
j =3D 0;
}
else if (( c =3D=3D '\r') || (c =3D=3D '\n')) {
if (uendidx =3D=3D 0)
cha[cha_idx].unitname[j] =3D '\0';
cha[cha_idx].resetnum[j] =3D '\0';
cha[cha_idx].curr_resetno =3D atol(cha[cha_idx].resetnum);
break;
}
}
=09
fprintf(stdout, "GOTGWIP: GOT %dth Chassis Unit Name =3D %s, =
resetno =3D %d, curr_resetno =3D %d\n",=20
cha_idx, cha[cha_idx].unitname, cha[cha_idx].resetno, =
cha[cha_idx].curr_resetno);
state[k] =3D GOTUNITNAME;
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
break;
}
break;
case GOTUNITNAME:
//
// After getting the Unit Name of the Gateway,=20
// we are ready to get or create a GW CDR file name based on the
// year, month, day, and Gateway IpAddress.=20
// The CDR file name format is:
//
// yymmdd.cdr.nnn
// =20
// where yy - last two digits of the year, mm- monith 01-12, dd - =
01-31, nnn- 1 to 999
// The cdr file shall be placed in ./xxx_xxx_xxx_xxx sub-directory =
under
// the current directory.
//=20
// If the file exists, then the system will open it.
// Otherwise, it will create the file. Everyday, it will create one
// cdr file per Gateway.=20
// =20
// First the server will get the today's date and create the date =
string
//
// fprintf(stdout, "GOTUNITNAME: InBuffer =3D %c, state[k] =3D %d\n", =
pCntx[k]->InBuffer[0], state[k]);
// fprintf(stdout, "GOTUNITNAME: CDRBuffer[%d] =3D %s\n", k, =
pCntx[k]->CDRBuffer);
time(&timer);
today =3D localtime(&timer);
sprintf(currdate, "%.2d%.2d%.2d",=20
((today->tm_year)+1900)%100,=20
((today->tm_mon)+1),
today->tm_mday
);=20
currdate[DATE_LEN] =3D '\0';
strcpy(cdrfilename, currdate);
cdrfilename[6] =3D '.'; =09
cdrfilename[7] =3D 'c';
cdrfilename[8] =3D 'd';
cdrfilename[9] =3D 'r';
cdrfilename[10] =3D '\0';
i =3D 0;
//
// Start to translate xxx.xxx.xxx.xxx address into xxx_xxx_xxx_xxx
//
for (i=3D0;i < IPADDR_LEN; i++)
{
c =3D cha[cha_idx].IpAddr[i];
// fprintf(stdout, "GOUNITNAME: IP Address Charactor =
%c\n",IpAddr[i]);
switch(c) {
case '\0':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
cdrdir[i] =3D cha[cha_idx].IpAddr[i];
break;
case '.':
cdrdir[i] =3D '_';
default:=09
break;=09
}
if (c =3D=3D '\0')
break;
}
=09
=09
fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, CDR directory =3D %s, =
CDR File Name =3D %s\n",=20
k, cdrdir, cdrfilename); =09
=09
//=20
// Create the total file path
//=20
strcpy(path, cdrfile_path);
strcat(path, cdrdir);
strcat(path, "\\");
if (_chdir(path))=20
{
if ((fret =3D _mkdir (path)) =3D=3D 0)=20
{
strcat(path, cdrfilename);
}
else {
fprintf(stderr, "Cannot Make directory =3D %s, error code =3D =
%d\n", path, fret);
return -1;
}
}
else {
// change back to the original cdr file path=20
_chdir (cdrfile_path);
strcat(path, cdrfilename);
if (dailyfilecount > 0) {
itoa (dailyfilecount, dailyfileindex, 10);
strcat(path, ".");
strcat(path, dailyfileindex);
}
}
fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d CDR File Name =3D %s\n", =
k, path);
//
// Open or create the cdr file
//
for (i=3D0; i < retry; i++ ) {
hFile[k] =3D CreateFile(
path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL
);
//
//Initialize overlap structure
// The system will read the cdr from the begginng
// i.e., Offset is set to 0
//
memset(&overlap[k], 0, sizeof (overlap[k]));
overlap[k].Offset =3D 0;
=09
if (hFile[k] =3D=3D INVALID_HANDLE_VALUE) {
fprintf(stdout, "GOTUNITNAME: create file failed, CDR File Name =
=3D %s\n", path);
Sleep(50);
}
else=20
break;
}
//=20
// Initialize a cdr record=20
//=20
for (i=3D0; i < MAX_REC_LEN; i++) cdrecord[i] =3D '\0';
// fprintf(stdout, "GOTUNITNAME: CONN ID=3D %d, hFile[%d] =3D %d, %s =
open for appended\n", k, k, hFile[k], cdrfilename);
i=3D0;
lsqno =3D 0;
recno =3D 0;
csqno =3D 0;
//=20
// Start to get the expected sequence number that the CDR Server=20
// will send to the Gateway to ask for the next CDR record with the
// expected sequence number.
// To do this, one has to read one character at a time from the CDR =
file
// It uses the separated, a newline char, to get a cdr record from =
the file
// For each cdr record in the file, it extracts its sequence =
number.
// It loops through each record and keep the highest sequence =
number.
// After getting the highest sequence number of all the cdr records =
in the file
// The expected sequence number is the highest sequence number plus =
one.
//=20
while (ReadFile(
hFile[k],
record,
1,
&numread,
&overlap[k]
))=20
{
//fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, recno# =3D %d, %dth =
char =3D %c\n", k, recno, i, record[0]);
switch(record[0]) {
case '\n':
case '\r':
case '\0':
// get the highest sequence number of all the records in the cdr =
file
// the last cdr record may not have the highest sequence no
for (j =3D 0; cdrecord[j]!=3D ',' ; j++)=20
{=20
seqno[j] =3D cdrecord[j];
}
seqno[j] =3D '\0';
csqno =3D atoi(seqno);
//lsqno =3D ((lsqno > csqno) ? lsqno: csqno);
// CH always send back sequence in ascending order until it =
starts to recycle
lsqno =3D csqno; =09
cdrecord[i] =3D '\0';
break;
default:
cdrecord [i] =3D record[0];=20
break;
}
if (cdrecord[i] =3D=3D '\0') {
recno++;
// fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, %dth cdrecord =3D =
%s, lenght =3D %d\n", k, recno, cdrecord, i);
i =3D 0;
}=20
else=20
i++;
overlap[k].Offset++;
}
if ((recno =3D=3D 0) || (cha[cha_idx].curr_resetno !=3D =
cha[cha_idx].resetno))
{
esqno =3D 1;
lastseqno[0] =3D '0';
lastseqno[1] =3D '\0';
fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, # of records =3D %d =
LastSeqNo =3D %s, ExpectedSeqNo =3D %d\n", k, recno, lastseqno, esqno);
}
else=20
{
esqno =3D lsqno + 1;
//fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, LastRec# =3D %d =
lsqno =3D %d, esqno =3D %d\n",=20
// k, recno, lsqno, esqno);
ltoa (lsqno, lastseqno, MAX_ESQN_LEN);
fprintf(stdout, "GOTUNITNAME:CONN ID =3D %d, # of records =3D %d, =
LastSeqNo =3D %s ExpectedSeqNo =3D %d\n", k, recno, lastseqno, esqno);
=09
}
=09
cha[cha_idx].resetno =3D cha[cha_idx].curr_resetno;
state[k] =3D GOTLASTSEQNO;
case GOTLASTSEQNO:
//
// Now we are ready to send back the expected sequence number to =
the Gateway.
//=20
pCntx[k]->nCDRBuffIndex =3D sizeof(lastseqno);
strncpy(pCntx[k]->CDRBuffer, lastseqno, pCntx[k]->nCDRBuffIndex);
pCntx[k]->CDRBuffer[pCntx[k]->nCDRBuffIndex++] =3D '\r';
pCntx[k]->CDRBuffer[pCntx[k]->nCDRBuffIndex++] =3D '\n';
=09
fprintf(stdout, "GOTLASTSEQNO:Send LastSeqNo %s back to Gateway\n", =
pCntx[k]->CDRBuffer);
WriteFile
(
(HANDLE)(pCntx[k]->sock),
pCntx[k]->CDRBuffer,
pCntx[k]->nCDRBuffIndex,
&pCntx[k]->dwWritten,
&pCntx[k]->ovOut
); =09
=09
// clear the CDRBuffer and reset index
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
//memset (pCntx[k]->CDRBuffer, 0, MAX_REC_LEN);
pCntx[k]->nCDRBuffIndex =3D 0;
state[k] =3D READY;
break;
case READY:
//
// Now the CDR Server is ready to receive CDR records from the =
Gateway.
// The Gateway may send some junk or special characters to the =
Gateway at this time
// The server will drop those junks and continue to read the next =
records.
// Notice that all CDRs are starting with digital charactors.
//
=09
if (pCntx[k]->InBuffer[0] =3D=3D '\n')
{
fprintf(stdout, "READY: CONNID =3D %d, Incoming String =3D %s\n", =
k, pCntx[k]->CDRBuffer);
switch (pCntx[k]->CDRBuffer[0] )=20
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
=09
//It must be a CDR record now
//write it into the cdrfile
// Check the current date to see if it is time=20
// to create another file due to the new date
//
time(&timer);
today =3D localtime(&timer);
sprintf(currdate, "%.2d%.2d%.2d",=20
((today->tm_year)+1900)%100,=20
((today->tm_mon)+1),
today->tm_mday
);=20
currdate[DATE_LEN] =3D '\0';
// fprintf(stdout, "READY: Current CDR File Name =3D %s and the =
current date =3D %s\n", cdrfilename, currdate);
if ((strncmp(currdate, cdrfilename, DATE_LEN-1) !=3D 0) ||
(recno >=3D maxcdrno))
{
CloseHandle(hFile[k]);
for(i=3D0; i<MAX_FILE_NAME_LEN; i++) path[i] =3D '\0';
for(i=3D0; i < DATE_LEN-1; i++) cdrfilename[i] =3D currdate[i];
strcpy(path, cdrfile_path);
strcat(path, cdrdir);
strcat(path, "\\");
strcat(path, cdrfilename);
if (dailyfilecount > 0)=20
{
itoa (dailyfilecount, dailyfileindex, 10);
strcat(path, ".");
strcat(path, dailyfileindex);
}
for (i=3D0; i < retry; i++) {
hFile[k] =3D CreateFile(
path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL
);
if (hFile[k] =3D=3D INVALID_HANDLE_VALUE) {
fprintf(stdout, "READY: open file failed, CDR File Name =3D =
%s\n", path);
Sleep(50);
=09
}
else {
recno =3D 0;
if (strncmp(currdate, cdrfilename, DATE_LEN-1) !=3D 0)=20
{
dailyfilecount =3D 0;
} else {
dailyfilecount++;
if (dailyfilecount >=3D 999)
dailyfilecount =3D 0;
}
break;
}
}
overlap[k].Offset =3D 0;
// fprintf(stdout, "READY: Created CDR File Name =3D %s and the =
current date =3D %s\n", cdrfilename, currdate);
}
pCntx[k]->CDRBuffer[pCntx[k]->nCDRBuffIndex] =3D '\0';
// get the expected sequence from the CDR record
i =3D 0;
while (pCntx[k]->CDRBuffer[i] !=3D ',') seqno[i] =3D =
pCntx[k]->CDRBuffer[i++];
seqno[i] =3D '\0';
csqno =3D atoi(seqno);
=09
//fprintf(stdout, "READY: incoming record seq no =3D %d and =
expected seq no =3D %d\n", csqno, esqno);
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->OutBuffer[i] =3D '\0';
pCntx[k]->nOutBuffIndex =3D 0;
fret =3D convert_cdr(pCntx[k]);
if ((fret !=3D 24) && (fret !=3D 20) && (fret !=3D 28))
{
fprintf(stderr, "CONN ID =3D %d, WARNING: the incoming CDR record =
may have missing fields, Number of fields =3D %d\n",k, fret);
}
for (i =3D 1; i < retry; i++) {
rc =3D WriteFile(
hFile[k],
pCntx[k]->OutBuffer,
pCntx[k]->nOutBuffIndex,
&pCntx[k]->dwWritten,
&overlap[k]);
if (rc) {
overlap[k].Offset +=3D pCntx[k]->dwWritten;
fprintf(stdout, "READY: CONN ID =3D %d:Write CDR =3D %s\n", k, =
pCntx[k]->OutBuffer);
for (i=3D0; i < MAX_ESQN_LEN; i++) lastseqno[i] =3D '\0';
ltoa (csqno, lastseqno, MAX_ESQN_LEN);
recno++;
break;
} else {
fprintf(stdout, "READY: CONN ID =3D %d:FileWrite Failed %dth =
time, file Handle =3D %d, rc =3D %d\n", k, i, hFile[k], rc);
Sleep (50);=09
}
}
// WARNING: if the incoming CDR sequence number is greater than =
the expected sequence=20
if (csqno > esqno) {
fprintf(stdout, "WARNING: CONN ID =3D %d: Some CDR records may be =
lost!\n");
fprintf(stdout, "WARNING: CONN ID =3D %d: Receiving CDR Sequence =
Number > Expected Sequence Number\n");
}
// set next expected sequence no for incoming record
esqno =3D csqno + 1;
//state[k] =3D GOTEXPECTEDSEQNO;
state[k] =3D READY;
// clear the CDRBuffer and reset index
=09
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
pCntx[k]->dwWritten=3D0;
break;
default:
// fprintf(stderr, "Get some charater %2x\n", =
pCntx[k]->CDRBuffer[0]);
for (i=3D0; i < MAX_REC_LEN; i++) pCntx[k]->CDRBuffer[i] =3D '\0';
pCntx[k]->nCDRBuffIndex =3D 0;
// get some junk
break;
}
}
default:
break;
}
=09
// Start a new read
if (IssueRead(pCntx[k]) < 0)
{
free(pCntx[k]);
CloseHandle(hFile[k]);
state[k] =3D AVAIL;
fprintf(stderr, "CONNID =3D %d, IssueRead Failed\n", k);
return 0;
}
}
}
free(pCntx[k]);
CloseHandle(hFile[k]);
state[k] =3D AVAIL;
return 0;
}
/*
* Call ReadFile to start an overlapped request
* on a socket. Make sure we handle errors
* that are recoverable.
*/
int IssueRead(struct ContextKey *pCntx)
{
int i =3D 0;
BOOL bResult;
int err;
int numRead;
while (++i)
{
// Request a single character
bResult =3D ReadFile(
(HANDLE)pCntx->sock,
pCntx->InBuffer,
1,
&numRead,
&pCntx->ovIn
);
// It succeeded immediately, but do not process it
// here, wait for the completion packet.
if (bResult)
return 1;
err =3D GetLastError();
// This is what we want to happen, it's not an error
if (err =3D=3D ERROR_IO_PENDING)
return 1;
=09
// Handle recoverable error
if ( err =3D=3D ERROR_INVALID_USER_BUFFER ||
err =3D=3D ERROR_NOT_ENOUGH_QUOTA ||
err =3D=3D ERROR_NOT_ENOUGH_MEMORY ||=20
err =3D=3D ERROR_WORKING_SET_QUOTA)
{
if ((i >=3D1) && (i <=3D 5))// I just picked a number
{
fprintf(stdout, "ISSUE_READ: CONN ID=3D %d, Error =3D %d, Sleep 200 =
mseconds to retry\n", pCntx->sid, err);
Sleep(25); // Wait around and try later
continue;
}
fprintf(stderr, "IssueRead - System ran out of non-paged =
space");
return -err;
}
break;
}
fprintf(stderr, "IssueRead - ReadFile failed.Error Code =3D %d\n", =
err);
return -err;
}
//
// Make sure we are running under the right versions
// of Windows NT (3.51, 4.0, or later)
//
void CheckOsVersion()
{
OSVERSIONINFO ver;
BOOL bResult;
ver.dwOSVersionInfoSize =3D sizeof(OSVERSIONINFO);
bResult =3D GetVersionEx((LPOSVERSIONINFO) &ver);
if ( (!bResult) ||
(ver.dwPlatformId !=3D VER_PLATFORM_WIN32_NT) )
{
FatalError("CDRSRV requires Windows NT 3.51 or later.");
}
}
//
// Error handler
//
void FatalError(char *s)
{
fprintf(stdout, "%s\n", s);
exit(EXIT_FAILURE);
}
void GetConfigInfo(char *pswd, int *maxchano, int *maxcdrno)
{
int i, j;
int numread;
char inbuf[4];
char buffer[MAX_REC_LEN];
char c;
OVERLAPPED overlap;
// initialize overlap structure
memset(&overlap, 0, sizeof (overlap));
overlap.Offset =3D 0;
// parsing the cdr server configuration file
//fprintf(stdout, "GetConfigInfo Read CDRSERVER Configuration File =
Handle =3D %d\n", ghFile);
i =3D 0;
=09
while (ReadFile(
ghFile,
inbuf,
1,
&numread,
&overlap
))=20
{
switch(inbuf[0]) {
=09
case '\n':
case '\r':
case '\0':
buffer[i] =3D '\0';
// get a line=20
if (strncmp (buffer, "//", 2) =3D=3D 0) {
//skip the comment line
//fprintf(stdout, "GetConfigInfo Get a comment line =3D %s\n", =
buffer);
// clear the buffer to get the next line
}=20
else if (strncmp(buffer, "cdr_password", 12) =3D=3D 0)=20
{
// fprintf(stdout, "GetConfigInfo Get Password =3D %s\n", buffer); =
// get the cdrpassword=20
j =3D 12;
c=3Dbuffer[j];
while (isspace(c)) c=3Dbuffer[j++]; // skip the blanks
while (isprint(c))=20
{
*(pswd) =3D c;
// fprintf(stdout, "GetConfigInfo pswd =3D %c\n", *pswd);
c =3D buffer[j++];
pswd++;
}
*pswd =3D '\0';
} else if (strncmp(buffer, "MAX_CHASSIS_NUM", 13) =3D=3D 0){
//fprintf(stdout, "GetConfigInfo Get MAX GW NUM LINE =3D %s\n", =
buffer); =09
j =3D 13;
c =3D buffer[j];
while (isspace(c)) c=3Dbuffer[j++]; // skip the blanks
*maxchano =3D atoi(&(buffer[j-1]));
} else if (strncmp(buffer, "max_cdr_per_file", 16) =3D=3D 0) {
//fprintf(stdout, "GetConfigInfo Get MAX CDR PER FILE LINE =3D =
%s\n", buffer);
j =3D 16;
while (isspace(buffer[j++])); //skip the blanks
*maxcdrno =3D atoi(&(buffer[j-1]));
}
// clear the buffer to get another line
for(i=3D0; i < MAX_REC_LEN; i++) buffer[i] =3D '\0';
i =3D 0; =09
break;
default:
buffer[i++] =3D inbuf[0];
break;
}
overlap.Offset++;
}
}
int convert_cdr(struct ContextKey *pCntx)
{
int i, field_cnt;
char c;
field_cnt =3D 0;
pCntx->nOutBuffIndex =3D 0;
for (i=3D0; i < pCntx->nCDRBuffIndex; i++)=20
{=20
c =3D pCntx->CDRBuffer[i];
if (c =3D=3D ',') {
field_cnt++;
if ((field_cnt > 1) && (pCntx->CDRBuffer[i-1] =3D=3D ','))=20
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D '-';
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D c;
} else if (c =3D=3D '\r') {
if (pCntx->CDRBuffer[i-1] =3D=3D ',')=20
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D '-';
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D ',';
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D c;
field_cnt++;
} else
pCntx->OutBuffer[pCntx->nOutBuffIndex++] =3D c;
}
return field_cnt;
}
------=_NextPart_000_0029_01C7778A.632E0120--