📄 servconn.cpp
字号:
/* * ServConn.cpp - part of the jEdit Launcher package * Copyright (C) 2001, 2002 John Gellene * jgellene@nyc.rr.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * Notwithstanding the terms of the General Public License, the author grants * permission to compile and link object code generated by the compilation of * this program with object code and libraries that are not subject to the * GNU General Public License, provided that the executable output of such * compilation shall be distributed with source code on substantially the * same basis as the jEditLauncher package of which this program is a part. * By way of example, a distribution would satisfy this condition if it * included a working makefile for any freely available make utility that * runs on the Windows family of operating systems. This condition does not * require a licensee of this software to distribute any proprietary software * (including header files and libraries) that is licensed under terms * prohibiting redistribution to third parties. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * A portion of the source code noted below is derived from code publicly * released by Unicode, Inc. * * $Id: ServConn.cpp,v 1.9 2002/03/24 16:56:42 jgellene Exp $ */#include "stdafx.h"#include "ServConn.h"#include "JELauncher.h"#include "LauncherLog.h"#include <winsock2.h> // winsock functionsServerConnection::ServerConnection(LPCTSTR lpszServerPath) : binary(false), port(0), key(0L), hSocket(0), connected(false), pServerPath(lpszServerPath) {}ServerConnection::~ServerConnection(){ if(connected) Disconnect();}bool ServerConnection::IsBinary() const{ return binary;}unsigned short ServerConnection::GetPort() const{ return port;}unsigned long ServerConnection::GetKey() const{ return key;}bool ServerConnection::IsConnected() const{ return connected;}HRESULT ServerConnection::FindServer(){ UINT nErrorMsg = 0; CHAR buffer[255]; ZeroMemory(buffer, 255); LauncherLog::Log(Debug, "[launcher] default code page is %d\n", AreFileApisANSI() ? GetACP() : GetOEMCP()); LauncherLog::Log(Debug, "[launcher] searching for server file %s\n", pServerPath); HANDLE h = ::CreateFile(pServerPath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //FLAG_SEQUENTIAL_SCAN, 0); LauncherLog::Log(Debug, "[launcher] Server file %s\n", (h != INVALID_HANDLE_VALUE ? "opened" : "not opened")); if(h == INVALID_HANDLE_VALUE) { LPSTR szErrMsg = 0; ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &szErrMsg, 0, NULL ); LauncherLog::Log(Debug, "[launcher] System error message: %s", szErrMsg); LocalFree((LPVOID)szErrMsg); } DWORD dwBytesRead; HRESULT hr = S_OK; if( h != INVALID_HANDLE_VALUE && ::ReadFile(h, (LPVOID)buffer, 255, &dwBytesRead, 0)) { // replaces sscanf char *s = buffer; int nFieldsRead = 0; // NOTE: test for binary (4.0) protocol if(*s == 'b') { binary = true; while(*s != 0 && *s != '\n') ++s; if(s - buffer < (long)dwBytesRead) ++s; } LauncherLog::Log(Debug, "[launcher] %s EditServer detected.\n", binary ? "Binary (v4.0)" : "Char (v3.2)"); port = (unsigned short)atoi(s); if(port != 0) ++nFieldsRead; while(*s != 0 && *s != '\n') ++s; if(s - buffer < (long)dwBytesRead) ++s; key = (unsigned long)atol(s); if(key != 0) ++nFieldsRead; if(nFieldsRead != 2) { hr = E_FAIL; switch(nFieldsRead) { case 0: LauncherLog::Log(Error, "[launcher] Port number in server file is invalid.\n"); CJEditLauncher::MakeErrorInfo("Port number in server file is invalid."); break; case 1: LauncherLog::Log(Error, "[launcher] Key number in server file is invalid.\n"); CJEditLauncher::MakeErrorInfo("Key number in server file is invalid."); break; default: LauncherLog::Log(Error, "[launcher] Server file could not be read.\n"); CJEditLauncher::MakeErrorInfo("Server file could not be read."); } } } else { hr = S_FALSE; LauncherLog::Log(Debug, "[launcher] Could not find server file.\n"); CJEditLauncher::MakeErrorInfo("Could not find server file."); } if(h != INVALID_HANDLE_VALUE) ::CloseHandle(h); return hr;}HRESULT ServerConnection::DeleteServerData(){ Clear(); return ::DeleteFile(pServerPath) ? S_OK : E_FAIL;}HRESULT ServerConnection::Connect(){ if(connected) return S_OK; if(port == 0 && S_OK != FindServer()) { return E_FAIL; } WSADATA wsa_data; if (WSAStartup(MAKEWORD(1, 0), &wsa_data) != 0) { LauncherLog::Log(Error, "[launcher] Could not start Windows socket service.\n"); CJEditLauncher::MakeErrorInfo("Could not start Windows socket service."); return E_FAIL; } hSocket = socket(PF_INET, SOCK_STREAM, 0); if(hSocket == INVALID_SOCKET) { LauncherLog::Log(Error, "[launcher] Invalid Windows socket.\n"); CJEditLauncher::MakeErrorInfo("Invalid Windows socket."); hSocket = 0; WSACleanup(); return E_FAIL; } struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = htonl(0x7f000001); address.sin_port = htons(port); if (connect(hSocket, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR) { if(WSAGetLastError() == WSAECONNREFUSED) { LauncherLog::Log(Error, "[launcher] jEdit EditServer refused connection.\n"); CJEditLauncher::MakeErrorInfo("jEdit EditServer refused connection."); } else { LauncherLog::Log(Error, "[launcher] Bad connection with jEdit EditServer.\n"); CJEditLauncher::MakeErrorInfo("Bad connection with jEdit EditServer."); } return E_FAIL; } else connected = true; return S_OK;}HRESULT ServerConnection::Disconnect(){ if(hSocket != 0) { closesocket(hSocket); hSocket = 0; } connected = false; WSACleanup(); return S_OK;}HRESULT ServerConnection::Clear(){ binary = false; port = 0; key = 0; return Disconnect();}HRESULT ServerConnection::SendData(char* pData, long nLength){ if(!connected) return S_FALSE; CHAR buf[32]; ZeroMemory(buf, 32); LPBYTE szUTF = 0; long len = 0; if(!binary) // NOTE: Version 3.2.2 EditServer { ultoa((ULONG)key, buf, 10); strcat(buf, "\n"); len = strlen(buf); } else // NOTE: Version 4.0 EditServer (beginning with 4.0pre4) { int outBufferLen = nLength * 4; szUTF = new BYTE[outBufferLen]; ConvertCharToUTF8(pData, nLength, szUTF, &outBufferLen); unsigned long nlKey = htonl(key); BYTE *s = (BYTE*)buf; memcpy(s, &nlKey, sizeof(unsigned long)); s += sizeof(key); unsigned short nsLen = htons(outBufferLen); memcpy(s, &nsLen, sizeof(int)); len = (long)(sizeof(unsigned long) + sizeof(unsigned short)); nLength = outBufferLen; pData = (char*)szUTF; } long sent = send(hSocket, buf, len, 0); if(len != sent) return E_FAIL; sent = send(hSocket, pData, nLength, 0); if(szUTF != 0) delete [] szUTF; return sent == nLength ? S_OK : E_FAIL;}/* --------------------------------------------------------------- *//* * The following code is derived from publicly released source code - * Copyright 2001 Unicode, Inc.; Unicode's disclaimer and * redistribution notice accompanying the original code follows: * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. * * Author: Mark E. Davis, 1994. * Rev History: Rick McGowan, fixes & updates May 2001. * * Revisions for jEditLauncher module: * (1) Uses only ConvertUTF16toUTF8() and related typedefs and manifest * constants. * (2) Adds casts to (UTF32) in "switch (bytesToWrite)" block to eliminate * compiler warnings * */typedef unsigned long UTF32; /* at least 32 bits */typedef unsigned short UTF16; /* at least 16 bits */typedef unsigned char UTF8; /* typically 8 bits */typedef unsigned char Boolean; /* 0 or 1 *//* Some fundamental constants */#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD#define UNI_MAX_BMP (UTF32)0x0000FFFF#define UNI_MAX_UTF16 (UTF32)0x0010FFFF#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFFtypedef enum { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ targetExhausted, /* insuff. room in target for conversion */ sourceIllegal /* source sequence is illegal/malformed */} ConversionResult;typedef enum { strictConversion = 0, lenientConversion} ConversionFlags;ConversionResult ConvertUTF16toUTF8 ( UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, const UTF8* targetEnd, ConversionFlags flags);/* --------------------------------------------------- */static const int halfShift = 10; /* used for shifting by 10 bits */static const UTF32 halfBase = 0x0010000UL;static const UTF32 halfMask = 0x3FFUL;#define UNI_SUR_HIGH_START (UTF32)0xD800#define UNI_SUR_HIGH_END (UTF32)0xDBFF#define UNI_SUR_LOW_START (UTF32)0xDC00#define UNI_SUR_LOW_END (UTF32)0xDFFF/* --------------------------------------------------------------------- *//* * Index into the table below with the first byte of a UTF-8 sequence to * get the number of trailing bytes that are supposed to follow it. */static const char trailingBytesForUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5};/* * Magic values subtracted from a buffer value during UTF8 conversion. * This table contains as many values as there might be trailing bytes * in a UTF-8 sequence. */static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL };/* * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed * into the first byte, depending on how many bytes follow. There are * as many entries in this table as there are UTF-8 sequence types. * (I.e., one byte sequence, two byte... six byte sequence.) */static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };/* --------------------------------------------------------------------- */ConversionResult ConvertUTF16toUTF8 ( UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, const UTF8* targetEnd, ConversionFlags flags) { ConversionResult result = conversionOK; UTF16* source = *sourceStart; UTF8* target = *targetStart; while (source < sourceEnd) { UTF32 ch; unsigned short bytesToWrite = 0; const UTF32 byteMask = 0xBF; const UTF32 byteMark = 0x80; ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) { UTF32 ch2 = *source; if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ result = sourceIllegal; break; } } else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) { --source; /* return to the illegal value itself */ result = sourceIllegal; break; } /* Figure out how many bytes the result will require */ if (ch < (UTF32)0x80) { bytesToWrite = 1; } else if (ch < (UTF32)0x800) { bytesToWrite = 2; } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; } else if (ch < (UTF32)0x200000) { bytesToWrite = 4; } else { bytesToWrite = 2; ch = UNI_REPLACEMENT_CHAR; } target += bytesToWrite; if (target > targetEnd) { target -= bytesToWrite; result = targetExhausted; break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } *sourceStart = source; *targetStart = target; return result;}/* end of Unicode, Inc. code *//* --------------------------------------------------------------------- */void ServerConnection::ConvertCharToUTF8(char* szIn, const int nInLength, LPBYTE szOut, int* pnOutLength){ // NOTE: Transforms char string to UTF-16 using Win32 API, then to UTF-8 const int bufferLength = nInLength + 1; wchar_t *szwBuf = new wchar_t[bufferLength]; UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; int nWritten = MultiByteToWideChar(nCodePage, 0, szIn, bufferLength, szwBuf, bufferLength);// LauncherLog::Log(Debug, "[launcher] Wide char data string: %S\n", szwBuf); wchar_t* pSource = szwBuf; LPBYTE pDest = szOut; ConversionResult result = ConvertUTF16toUTF8(&pSource, szwBuf + nInLength, &pDest, szOut + *pnOutLength, lenientConversion); *pDest = 0; *pnOutLength = (int)(pDest - szOut); delete [] szwBuf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -