#include "ofxTCPClient.h"
#include "ofAppRunner.h"
#include "ofxNetworkUtils.h"
#include "ofLog.h"
using namespace std;
ofxTCPClient::ofxTCPClient(){
connected = false;
messageSize = 0;
port = 0;
index = -1;
str = "";
tmpStr = "";
ipAddr ="000.000.000.000";
partialPrevMsg = "";
messageDelimiter = "[/TCP]";
memset(tmpBuff, 0, TCP_MAX_MSG_SIZE+1);
}
ofxTCPClient::~ofxTCPClient(){
close();
}
void ofxTCPClient::setVerbose(bool _verbose){
ofLogWarning("ofxTCPClient") << "setVerbose(): is deprecated, replaced by ofLogWarning and ofLogError";
}
bool ofxTCPClient::setup(string ip, int _port, bool blocking){
ofxTCPSettings settings(ip, _port);
settings.blocking = blocking;
return setup(settings);
}
bool ofxTCPClient::setup(const ofxTCPSettings & settings){
if( !TCPClient.Create() ){
ofLogError("ofxTCPClient") << "setup(): couldn't create client";
return false;
}else if( !TCPClient.Connect((char *)settings.address.c_str(), settings.port) ){
ofLogError("ofxTCPClient") << "setup(): couldn't connect to " << settings.address << " " << settings.port;
TCPClient.Close();
return false;
}
TCPClient.SetNonBlocking(!settings.blocking);
setMessageDelimiter(settings.messageDelimiter);
port = settings.port;
ipAddr = settings.address;
connected = true;
return true;
}
bool ofxTCPClient::setupConnectionIdx(int _index, bool blocking){
index = _index;
InetAddr addr;
if( TCPClient.GetRemoteAddr(&addr) ){
port = addr.GetPort();
ipAddr = addr.DottedDecimal();
}
TCPClient.SetNonBlocking(!blocking);
connected = true;
return true;
}
bool ofxTCPClient::close(){
if( connected ){
if( !TCPClient.Close() ){
ofLogError("ofxTCPClient") << "close(): couldn't close client";
return false;
}else{
ofLogVerbose("ofxTCPClient") << "closing client";
connected = false;
return true;
}
}else{
return true;
}
}
void ofxTCPClient::setMessageDelimiter(string delim){
if(delim != ""){
messageDelimiter = delim;
}
}
bool ofxTCPClient::send(string message){
if(!connected){
ofLogWarning("ofxTCPClient") << "send(): not connected, call setup() first";
return false;
}
message = partialPrevMsg + message + messageDelimiter;
message += (char)0;
int ret = TCPClient.SendAll( message.c_str(), message.length() );
int errorCode = 0;
if(ret<0) errorCode = ofxNetworkCheckError();
if( isClosingCondition(ret, errorCode) ){
ofLogWarning("ofxTCPClient") << "send(): client disconnected";
close();
return false;
}else if(ret<0){
ofLogError("ofxTCPClient") << "send(): sending failed";
return false;
}else if(ret<(int)message.length()){
partialPrevMsg=message.substr(ret);
return true;
}else{
partialPrevMsg = "";
return true;
}
}
bool ofxTCPClient::sendRawMsg(const char * msg, int size){
if(!connected){
ofLogWarning("ofxTCPClient") << "sendRawMsg(): not connected, call setup() first";
return false;
}
tmpBuffSend.append(msg,size);
tmpBuffSend.append(messageDelimiter.c_str(),messageDelimiter.size());
int ret = TCPClient.SendAll( tmpBuffSend.getData(), tmpBuffSend.size() );
int errorCode = 0;
if(ret<0) errorCode = ofxNetworkCheckError();
if( isClosingCondition(ret, errorCode) ){
ofLogWarning("ofxTCPClient") << "sendRawMsg(): client disconnected";
close();
return false;
}else if(ret<0){
ofLogError("ofxTCPClient") << "sendRawMsg(): sending failed";
return false;
}else if(ret<size){
tmpBuffSend.set(&tmpBuffSend.getData()[ret],tmpBuffSend.size()-ret);
return true;
}else{
tmpBuffSend.clear();
return true;
}
}
bool ofxTCPClient::sendRaw(string message){
if( message.length() == 0) return false;
int ret = TCPClient.SendAll(message.c_str(), message.length());
int errorCode = 0;
if(ret<0) errorCode = ofxNetworkCheckError();
if( isClosingCondition(ret, errorCode) ){
ofLogError("ofxTCPClient") << "sendRawBytes(): sending failed";
close();
return false;
}else{
return ret > 0;
}
}
bool ofxTCPClient::sendRawBytes(const char* rawBytes, const int numBytes){
if( numBytes <= 0) return false;
int ret = TCPClient.SendAll(rawBytes, numBytes);
int errorCode = 0;
if(ret<0) errorCode = ofxNetworkCheckError();
if( isClosingCondition(ret, errorCode) ){
ofLogError("ofxTCPClient") << "sendRawBytes(): sending failed";
close();
return false;
}else{
return ret > 0;
}
}
int ofxTCPClient::getNumReceivedBytes(){
return messageSize;
}
static void removeZeros(char * buffer, int size){
for(int i=0;i<size-1;i++){
if(buffer[i]==(char)0){
for(int j=i;j<size-1;j++){
buffer[j]=buffer[j+1];
}
buffer[size-1]=(char)0;
}
}
}
bool ofxTCPClient::isClosingCondition(int messageSize, int errorCode){
return (messageSize == SOCKET_ERROR && (errorCode == OFXNETWORK_ERROR(CONNRESET) || errorCode == OFXNETWORK_ERROR(CONNABORTED) || errorCode == OFXNETWORK_ERROR(CONNREFUSED) || errorCode == EPIPE || errorCode == OFXNETWORK_ERROR(NOTCONN)))
|| (messageSize == 0 && !TCPClient.IsNonBlocking() && TCPClient.GetTimeoutReceive()!=NO_TIMEOUT);
}
string ofxTCPClient::receive(){
str = "";
char byte;
while(peekReceiveRawBytes(&byte, 1)>0){
int length=0;
if(tmpStr.find(messageDelimiter)==string::npos){
memset(tmpBuff, 0, TCP_MAX_MSG_SIZE+1);
length = TCPClient.Receive(tmpBuff, TCP_MAX_MSG_SIZE);
if(length>0){
removeZeros(tmpBuff,length);
tmpStr += tmpBuff;
}
}
int errorCode = 0;
if(length<0) errorCode = ofxNetworkCheckError();
if(isClosingCondition(length,errorCode)){
close();
if(tmpStr.length()==0) {
return "";
}
}
if(tmpStr.find(messageDelimiter)!=string::npos){
str=tmpStr.substr(0,tmpStr.find(messageDelimiter));
tmpStr=tmpStr.substr(tmpStr.find(messageDelimiter)+messageDelimiter.size());
return str;
}
}
return "";
}
static int findDelimiter(char * data, int size, string delimiter){
unsigned int posInDelimiter=0;
for(int i=0;i<size;i++){
if(data[i]==delimiter[posInDelimiter]){
posInDelimiter++;
if(posInDelimiter==delimiter.size()) return i-delimiter.size()+1;
}else{
posInDelimiter=0;
}
}
return -1;
}
int ofxTCPClient::receiveRawMsg(char * receiveBuffer, int numBytes){
int length=-2;
if(findDelimiter(tmpBuffReceive.getData(),tmpBuffReceive.size(),messageDelimiter)==-1){
memset(tmpBuff, 0, TCP_MAX_MSG_SIZE);
length = receiveRawBytes(tmpBuff, TCP_MAX_MSG_SIZE);
if(length>0){
tmpBuffReceive.append(tmpBuff,length);
}
}
int posDelimiter = findDelimiter(tmpBuffReceive.getData(),tmpBuffReceive.size(),messageDelimiter);
if(posDelimiter>0){
memcpy(receiveBuffer,tmpBuffReceive.getData(),posDelimiter);
if(tmpBuffReceive.size() > (unsigned int) posDelimiter + messageDelimiter.size()){
memcpy(tmpBuff,tmpBuffReceive.getData()+posDelimiter+messageDelimiter.size(),tmpBuffReceive.size()-(posDelimiter+messageDelimiter.size()));
tmpBuffReceive.set(tmpBuff,tmpBuffReceive.size()-(posDelimiter+messageDelimiter.size()));
}else{
tmpBuffReceive.clear();
}
}
if(posDelimiter>0){
return posDelimiter;
}else{
return 0;
}
}
int ofxTCPClient::receiveRawBytes(char * receiveBuffer, int numBytes){
messageSize = TCPClient.Receive(receiveBuffer, numBytes);
int errorCode = 0;
if(messageSize<0) errorCode = ofxNetworkCheckError();
if(isClosingCondition(messageSize, errorCode)){
close();
}
return messageSize;
}
int ofxTCPClient::peekReceiveRawBytes(char * receiveBuffer, int numBytes){
messageSize = TCPClient.PeekReceive(receiveBuffer, numBytes);
int errorCode = 0;
if(messageSize<0) errorCode = ofxNetworkCheckError();
if(isClosingCondition(messageSize, errorCode)){
close();
}
return messageSize;
}
string ofxTCPClient::receiveRaw(){
messageSize = TCPClient.Receive(tmpBuff, TCP_MAX_MSG_SIZE);
int errorCode = 0;
if(messageSize<0) errorCode = ofxNetworkCheckError();
if(isClosingCondition(messageSize, errorCode)){
close();
}else if(messageSize>=0 && messageSize<TCP_MAX_MSG_SIZE) {
tmpBuff[messageSize] = 0;
}
return tmpBuff;
}
bool ofxTCPClient::isConnected(){
if (connected) {
if (!TCPClient.CheckIsConnected()) {
close();
}
}
return connected;
}
int ofxTCPClient::getPort(){
return port;
}
string ofxTCPClient::getIP(){
return ipAddr;
}
Comments