Author: bdash
Date: 2005-07-12 15:08:54 +1200 (Tue, 12 Jul 2005)
New Revision: 359
Added:
trunk/msn/impl/
trunk/msn/impl/authdata.h
trunk/msn/impl/buddy.cpp
trunk/msn/impl/buddy.h
trunk/msn/impl/connection.cpp
trunk/msn/impl/connection.h
trunk/msn/impl/filetransfer.cpp
trunk/msn/impl/filetransfer.h
trunk/msn/impl/invitation.cpp
trunk/msn/impl/invitation.h
trunk/msn/impl/md5.cpp
trunk/msn/impl/md5.h
trunk/msn/impl/message.cpp
trunk/msn/impl/message.h
trunk/msn/impl/notificationserver.cpp
trunk/msn/impl/notificationserver.h
trunk/msn/impl/sstream_fix.h
trunk/msn/impl/switchboardserver.cpp
trunk/msn/impl/switchboardserver.h
Removed:
trunk/msn/authdata.cpp
trunk/msn/authdata.h
trunk/msn/buddy.cpp
trunk/msn/buddy.h
trunk/msn/connection.cpp
trunk/msn/connection.h
trunk/msn/filetransfer.cpp
trunk/msn/filetransfer.h
trunk/msn/invitation.cpp
trunk/msn/invitation.h
trunk/msn/md5.cpp
trunk/msn/md5.h
trunk/msn/message.cpp
trunk/msn/message.h
trunk/msn/notificationserver.cpp
trunk/msn/notificationserver.h
trunk/msn/sstream_fix.h
trunk/msn/switchboardserver.cpp
trunk/msn/switchboardserver.h
Modified:
trunk/msn/errorcodes.h
trunk/msn/externals.h
trunk/msn/msn.h
trunk/msn/msntest.cpp
trunk/msn/util.cpp
Log:
Beginnings of huge restructuring. It compiles... due to the 500+ lines that
got commented out.
Deleted: trunk/msn/authdata.cpp
===================================================================
--- trunk/msn/authdata.cpp 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/authdata.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,24 +0,0 @@
-/*
- * authdata.cpp
- * libmsn
- *
- * Created by Mark Rowe on Mon Mar 22 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <msn/authdata.h>
-
Deleted: trunk/msn/authdata.h
===================================================================
--- trunk/msn/authdata.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/authdata.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,44 +0,0 @@
-#ifndef __msn_authdata_h__
-#define __msn_authdata_h__
-
-/*
- * authdata.h
- * libmsn
- *
- * Created by Mark Rowe on Mon Mar 22 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <string>
-#include <msn/passport.h>
-#include <msn/uncopyable.h>
-
-namespace MSN
-{
- class AuthData : private Uncopyable
- {
-public:
- Passport username;
-
- AuthData(const Passport & username_) : username(username_) {};
- AuthData(const AuthData & auth_) : username(auth_.username) {};
- virtual ~AuthData() {};
-
- AuthData &operator=(const AuthData & auth_) { username =
auth_.username; return *this; };
- };
-}
-#endif
Deleted: trunk/msn/buddy.cpp
===================================================================
--- trunk/msn/buddy.cpp 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/buddy.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,74 +0,0 @@
-/*
- * buddy.cpp
- * libmsn
- *
- * Created by Mark Rowe on Mon Apr 19 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <msn/buddy.h>
-#include <cassert>
-
-namespace MSN
-{
- std::string buddyStatusToString(BuddyStatus state)
- {
- switch (state)
- {
- case STATUS_AVAILABLE:
- return "NLN";
- case STATUS_BUSY:
- return "BSY";
- case STATUS_IDLE:
- return "IDL";
- case STATUS_BERIGHTBACK:
- return "BRB";
- case STATUS_AWAY:
- return "AWY";
- case STATUS_ONTHEPHONE:
- return "PHN";
- case STATUS_OUTTOLUNCH:
- return "LUN";
- case STATUS_INVISIBLE:
- return "HDN";
- default:
- assert(false);
- }
- }
-
- BuddyStatus buddyStatusFromString(std::string state)
- {
- if (state == "NLN")
- return STATUS_AVAILABLE;
- else if (state == "BSY")
- return STATUS_BUSY;
- else if (state == "IDL")
- return STATUS_IDLE;
- else if (state == "BRB")
- return STATUS_BERIGHTBACK;
- else if (state == "AWY")
- return STATUS_AWAY;
- else if (state == "PHN")
- return STATUS_ONTHEPHONE;
- else if (state == "LUN")
- return STATUS_OUTTOLUNCH;
- else if (state == "HDN")
- return STATUS_INVISIBLE;
- else
- throw std::runtime_error("Unknown status!");
- }
-}
Deleted: trunk/msn/buddy.h
===================================================================
--- trunk/msn/buddy.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/buddy.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,163 +0,0 @@
-#ifndef __msn_buddy_h__
-#define __msn_buddy_h__
-
-/*
- * buddy.h
- * libmsn
- *
- * Created by Mark Rowe on Mon Apr 19 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <string>
-#include <list>
-#include <msn/passport.h>
-#include <msn/uncopyable.h>
-
-namespace MSN
-{
- /** The online state of a buddy.
- */
-
- enum BuddyStatus
- {
- STATUS_AVAILABLE, /**< NLN */
- STATUS_BUSY, /**< BSY */
- STATUS_IDLE, /**< IDL */
- STATUS_BERIGHTBACK, /**< BRB */
- STATUS_AWAY, /**< AWY */
- STATUS_ONTHEPHONE, /**< PHN */
- STATUS_OUTTOLUNCH, /**< OTL */
- STATUS_INVISIBLE /**< HDN */
- };
-
- /** Maps the BuddyStatus @a s into the MSN protocol-level name for the
status */
- std::string buddyStatusToString(BuddyStatus s);
-
- /** Maps the MSN protocol-level status name @a s into the corresponding
BuddyStatus value */
- BuddyStatus buddyStatusFromString(std::string s);
-
- class Group;
-
- /** The Buddy class contains information about a member of a buddy list.
- *
- * Each Buddy is made up of their passport address (@a userName),
- * user-visible display name (@a friendlyName), zero or more @a
phoneNumbers,
- * and zero or more @a groups on the buddy list that they belong to.
- *
- * It is only currently used during MSN::Callbacks::gotBuddyListInfo to
- * store contact information about a buddy that was retrieved during
- * the buddy list synchronisation process.
- */
- class Buddy : private Uncopyable
- {
- /** @todo BPR's need to be handled at any time, not just when
syncing. */
-public:
- /** The PhoneNumber class contains information about a single phone
number
- * that is retrieved during the buddy list synchronisation process.
- */
- class PhoneNumber : private Uncopyable
- {
-public:
- /** The name of this phone number.
- *
- * @todo Should this be an enumeration containing the possible
- * types of phone number?
- */
- std::string title;
-
- /** The phone number */
- std::string number;
-
- /** @todo Document me! */
- bool enabled;
-
- /** Initialize a PhoneNumber with the given @a title_ and phone @a
number_ */
- PhoneNumber(std::string title_, std::string number_, bool
enabled_=true)
- : title(title_), number(number_), enabled(enabled_) {};
-
- PhoneNumber(const PhoneNumber & phoneNumber_) :
title(phoneNumber_.title), number(phoneNumber_.number),
enabled(phoneNumber_.enabled) {};
- PhoneNumber &operator=(const PhoneNumber & phoneNumber_)
- {
- title = phoneNumber_.title;
- number = phoneNumber_.number;
- enabled = phoneNumber_.enabled;
- return *this;
- }
- };
-
- /** Their passport address */
- Passport userName;
-
- /** Their friendly name */
- std::string friendlyName;
-
- /** A list of phone numbers related to this buddy */
- std::list<Buddy::PhoneNumber> phoneNumbers;
-
- /** A list of Group's that this buddy is a member of */
- std::list<Group *> groups;
-
- /** Initialize the Buddy with the given @a userName_ and @a
friendlyName_ */
- Buddy(Passport userName_, std::string friendlyName_) :
- userName(userName_), friendlyName(friendlyName_),
- phoneNumbers(), groups() {};
-
- Buddy(const Buddy & buddy_) : userName(buddy_.userName),
friendlyName(buddy_.friendlyName), phoneNumbers(buddy_.phoneNumbers),
groups(buddy_.groups) {};
- Buddy &operator=(const Buddy & buddy_)
- {
- userName = buddy_.userName;
- friendlyName = buddy_.friendlyName;
- phoneNumbers = buddy_.phoneNumbers;
- groups = buddy_.groups;
- return *this;
- }
-
- /** Compare two buddies for equality based on userName */
- bool const operator==(const Buddy &other) { return userName ==
other.userName; }
- };
-
- /** The Group class represents a group of contacts on the buddy list.
- *
- * Each group is represented by an integer @a groupID and has a
user-visible
- * @a name.
- */
- class Group : private Uncopyable
- {
-public:
- /** The group ID */
- int groupID;
-
- /** The group name */
- std::string name;
-
- /** A list of buddies in the group */
- std::list<Buddy *> buddies;
-
- /** Initialize a Group with the given @a groupID_ and @a name_ */
- Group(int groupID_, std::string name_)
- : groupID(groupID_), name(name_), buddies() {};
-
- /** Initialize an empty, invalid group. */
- Group() : groupID(-1), name("INVALID"), buddies() {};
-
- Group(const Group & group_) : groupID(group_.groupID),
name(group_.name), buddies(group_.buddies) {};
- Group &operator=(const Group & group_) { groupID = group_.groupID;
name = group_.name; buddies = group_.buddies; return *this; }
- };
-}
-
-#endif
Deleted: trunk/msn/connection.cpp
===================================================================
--- trunk/msn/connection.cpp 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/connection.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,313 +0,0 @@
-/*
- * connection.cpp
- * libmsn
- *
- * Created by Mark Rowe on Mon Mar 22 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <msn/connection.h>
-#include <msn/errorcodes.h>
-#include <msn/util.h>
-#include <msn/passport.h>
-#include <msn/externals.h>
-#include <msn/notificationserver.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#else
-#include <winsock.h>
-#include <io.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <cerrno>
-#include <time.h>
-#include <cassert>
-
-namespace MSN
-{
- std::map<std::string, void (Connection::*)(std::vector<std::string> &,
std::string, std::string)> Connection::messageHandlers;
- static std::vector<std::string> errors;
-
- Connection::Connection()
- : sock(0), connected(false), trID(1), readBuffer(), writeBuffer()
- {
- srand((unsigned int) time(NULL));
-
- if (errors.size() != 0)
- {
- assert(errors.size() == 1000);
- }
- else
- {
- errors.resize(1000);
- for (int a = 0; a < 1000; a++)
- {
- errors[a] = "Unknown error code";
- }
-
- errors[200] = "Syntax error";
- errors[201] = "Invalid parameter";
- errors[205] = "Invalid user";
- errors[206] = "Domain name missing from username";
- errors[207] = "Already logged in";
- errors[208] = "Invalid username";
- errors[209] = "Invalid friendly name";
- errors[210] = "List full";
- errors[215] = "This user is already on this list or in this
session";
- errors[216] = "Not on list";
- errors[218] = "Already in this mode";
- errors[219] = "This user is already in the opposite list";
- errors[280] = "Switchboard server failed";
- errors[281] = "Transfer notification failed";
- errors[300] = "Required fields missing";
- errors[302] = "Not logged in";
- errors[500] = "Internal server error";
- errors[501] = "Database server error";
- errors[510] = "File operation failed at server";
- errors[520] = "Memory allocation failed on server";
- errors[600] = "The server is too busy";
- errors[601] = "The server is unavailable";
- errors[602] = "A Peer Notification Server is down";
- errors[603] = "Database connection failed";
- errors[604] = "Server going down for maintenance";
- errors[707] = "Server failed to create connection";
- errors[711] = "Blocking write failed on server";
- errors[712] = "Session overload on server";
- errors[713] = "You have been too active recently. Slow down!";
- errors[714] = "Too many sessions open";
- errors[715] = "Not expected";
- errors[717] = "Bad friend file on server";
- errors[911] = "Authentication failed. Check that you typed your
username and password correctly.";
- errors[913] = "This action is not allowed while you are offline";
- errors[920] = "This server is not accepting new users";
- }
-
- if (messageHandlers.size() == 0)
- {
- messageHandlers["text/plain"] =
&Connection::message_plain;
- messageHandlers["text/x-msmsgsinitialemailnotification"] =
&Connection::message_initial_email_notification;
- messageHandlers["text/x-msmsgsemailnotification"] =
&Connection::message_email_notification;
- messageHandlers["text/x-msmsgsinvite"] =
&Connection::message_invitation;
- messageHandlers["text/x-msmsgscontrol"] =
&Connection::message_typing_user;
- }
- }
-
- Connection::~Connection() {}
-
- void Connection::disconnect()
- {
-
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
- ::close(this->sock);
- this->sock = -1;
- this->writeBuffer.erase();
- this->readBuffer.erase();
- this->trID = 1;
- }
-
- std::vector<std::string> Connection::getLine()
- {
- assert(this->isWholeLineAvailable());
- std::string s = this->readBuffer.substr(0,
this->readBuffer.find("\r\n"));
- this->myNotificationServer()->externalCallbacks.log(0, (s +
"\n").c_str());
- return splitString(s, " ");
- }
-
- bool Connection::isWholeLineAvailable()
- {
- return this->readBuffer.find("\r\n") != std::string::npos;
- }
-
- void Connection::errorOnSocket(int errno_)
- {
- this->myNotificationServer()->externalCallbacks.showError(this,
strerror(errno_));
- this->disconnect();
- }
-
- void Connection::socketConnectionCompleted()
- {
- this->connected = true;
-
- // We know that we are connected, so this will try writing to the
network.
- size_t writtenLength = this->write(this->writeBuffer, 1);
- this->writeBuffer = this->writeBuffer.substr(writtenLength);
- }
-
- size_t Connection::write(std::string s, bool log) throw
(std::runtime_error)
- {
- if (! this->connected)
- this->writeBuffer.append(s);
- else
- {
- if (log)
- this->myNotificationServer()->externalCallbacks.log(1,
s.c_str());
-
- size_t written = 0;
- while (written < s.size())
- {
- size_t newWritten = ::send(this->sock,
s.substr(written).c_str(), (int) (s.size() - written), 0);
- if (newWritten <= 0)
- {
- if (errno == EAGAIN)
- continue;
- else
- break;
- }
- written += newWritten;
- }
- if (written != s.size())
- {
- this->errorOnSocket(errno);
- return written;
- }
- }
- return s.size();
- }
-
- size_t Connection::write(std::ostringstream & ss, bool log) throw
(std::runtime_error)
- {
- std::string s = ss.str();
- size_t result = write(s, log);
- return result;
- }
-
- void Connection::dataArrivedOnSocket()
- {
- char tempReadBuffer[8192];
- int amountRead = ::recv(this->sock, &tempReadBuffer[0], 8192, 0);
- if (amountRead < 0)
- {
- if (errno == EAGAIN)
- return;
-
- // We shouldn't get EAGAIN here because dataArrivedOnSocket
- // is only called when select/poll etc has told us that
- // the socket is readable.
- // assert(errno != EAGAIN);
-
- this->myNotificationServer()->externalCallbacks.showError(this,
strerror(errno));
- this->disconnect();
- }
- else if (amountRead == 0)
- {
- this->myNotificationServer()->externalCallbacks.showError(this,
"Connection closed by remote endpoint.");
- this->disconnect();
- }
- else
- {
- this->readBuffer += std::string(tempReadBuffer, amountRead);
- try
- {
- handleIncomingData();
- }
- catch (std::exception & e)
- {
-
this->myNotificationServer()->externalCallbacks.showError(this, e.what());
- }
- }
- }
-
- void Connection::handle_MSG(std::vector<std::string> & args)
- {
- int msglen;
- std::string msg;
- std::string mime;
- std::string body;
- size_t tmp;
-
- msglen = decimalFromString(args[3]);
- msg = this->readBuffer.substr(0, msglen);
- this->readBuffer = this->readBuffer.substr(msglen);
-
- body = msg.substr(msg.find("\r\n\r\n") + 4);
- mime = msg.substr(0, msg.size() - body.size());
-
- std::string contentType;
- Message::Headers headers(mime);
- contentType = headers["Content-Type"];
-
- if ((tmp = contentType.find("; charset")) != std::string::npos)
- contentType = contentType.substr(0, tmp);
-
- std::map<std::string, void (Connection::*)(std::vector<std::string> &,
std::string, std::string)>::iterator i = messageHandlers.find(contentType);
- if (i != messageHandlers.end())
- (this->*(messageHandlers[contentType]))(args, mime, body);
- }
-
- void Connection::message_plain(std::vector<std::string> & args,
std::string mime, std::string body)
- {
- Message msg(body, mime);
-
-
this->myNotificationServer()->externalCallbacks.gotInstantMessage(static_cast<SwitchboardServerConnection
*>(this),
- args[1], decodeURL(args[2]), &msg);
- }
-
- void
Connection::message_initial_email_notification(std::vector<std::string> & args,
std::string mime, std::string body)
- {
- std::string unreadInbox;
- std::string unreadFolder;
- int unreadInboxCount = 0, unreadFolderCount = 0;
-
- // Initial email notifications body is a set of MIME headers
- Message::Headers headers(body);
-
- unreadInbox = headers["Inbox-Unread"];
- unreadFolder = headers["Folders-Unread"];
- if (! unreadInbox.empty())
- unreadInboxCount = decimalFromString(unreadInbox);
-
- if (! unreadFolder.empty())
- unreadFolderCount = decimalFromString(unreadFolder);
-
-
this->myNotificationServer()->externalCallbacks.gotInitialEmailNotification(this,
unreadInboxCount, unreadFolderCount);
- }
-
-
- void Connection::message_email_notification(std::vector<std::string> &
args, std::string mime, std::string body)
- {
- // New email notifications body is a set of MIME headers
- Message::Headers headers(body);
-
- std::string from = headers["From-Addr"];
- std::string subject = headers["Subject"];
-
-
this->myNotificationServer()->externalCallbacks.gotNewEmailNotification(this,
from, subject);
- }
-
-
- void Connection::message_invitation(std::vector<std::string> & args,
std::string mime, std::string body)
- {
- static_cast<SwitchboardServerConnection
*>(this)->handleInvite(args[1], decodeURL(args[2]), mime, body);
- }
-
- void Connection::message_typing_user(std::vector<std::string> & args,
std::string mime, std::string body)
- {
- this->myNotificationServer()->externalCallbacks.buddyTyping(this,
args[1], decodeURL(args[2]));
- }
-
- void Connection::showError(int errorCode)
- {
- std::ostringstream buf_;
- buf_ << "Error code: " << errorCode << " (" << errors[errorCode] <<
")";
- this->myNotificationServer()->externalCallbacks.showError(this,
buf_.str());
- }
-}
Deleted: trunk/msn/connection.h
===================================================================
--- trunk/msn/connection.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/connection.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,184 +0,0 @@
-#ifndef __msn_connection_h__
-#define __msn_connection_h__
-
-/*
- * connection.h
- * libmsn
- *
- * Created by Mark Rowe on Mon Mar 22 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <string>
-#include <list>
-#include <vector>
-#include <map>
-#include <msn/sstream_fix.h>
-#include <msn/uncopyable.h>
-#include <stdexcept>
-
-namespace MSN
-{
- class callback;
- class Message;
- class Passport;
- class NotificationServerConnection;
- class SwitchboardServerConnection;
- class FileTransferConnection;
- class FileTransferInvitation;
-
- /** An abstract base class that represents a connection to another
computer.
- *
- * Connection provides an interface and some functionality that is common
- * to notification, switchboard and file transfer connections.
- *
- * @todo Connection should have a read buffer that stores all incoming data
- * that is waiting to be processed. Member functions should use that
- * for necessary data, and <em>not</em> call Connection::readExactly.
- */
- class Connection : private Uncopyable
- {
- friend class SwitchboardServerConnection;
- friend class NotificationServerConnection;
- friend class FileTransferConnection;
- friend class FileTransferInvitation;
-
-public:
- /** The socket which connects this Connection to another computer
- *
- * @deprecated In the future, this member will be made private. Any
- * functions that access this member should be converted
to
- * member functions of a subclass.
- */
- int sock;
-
- /** Indicates whether a connection has been established.
- *
- * @todo This is currently public only because
FileTransferInvitation::receiveFile
- * accesses it. It should be made protected in the future, and
- * FileTransferInvitation refactored to remove it's dependency
on
- * this attribute.
- */
- bool connected;
-
-private:
- /** The transaction ID of the next command to be sent.
- */
- int trID;
-
- std::string readBuffer;
-public:
- Connection();
- virtual ~Connection();
-
- /** Connect ourself to @a hostname on @a port.
- */
- virtual void connect(const std::string & hostname, unsigned int port)
= 0;
-
- /** Close the current connection.
- *
- * This should not be called if the connection is already disconnected.
- */
- virtual void disconnect() = 0;
-
- /** @name External Socket Hooks
- *
- * These members should be called whenever an appropriate socket event
- * occurs.
- */
- /** @{ */
-
- /** New data is available on the connection.
- */
- virtual void dataArrivedOnSocket();
-
- /** The connection has been established.
- */
- virtual void socketConnectionCompleted();
-
- /** The socket is ready for data to be written to it.
- */
- virtual void socketIsWritable() {};
-
- /** An error has occurred on the socket.
- */
- virtual void errorOnSocket(int errno_);
- /** @} */
-
- /** Notify the calling library that an error with code @a errorCode has
- * occured.
- */
- void showError(int errorCode);
-
- /** Is this Connection connected to a remote endpoint?
- */
- bool isConnected() { return this->connected; };
-
- /** Retrieve the parent NotificationServerConnection from this
connection */
- virtual NotificationServerConnection *myNotificationServer() = 0;
-private:
- /** Process a @c <code>MSG</code> command.
- *
- * This method will read the remaining message data from the network
- * and then delegates to private @c message_* functions based on the
- * @c Content-Type header found in the message.
- */
- void handle_MSG(std::vector<std::string> & args);
-
- virtual void handleIncomingData() = 0;
-
- /** Dispatch a command to its appropriate handler routines based on @a
args.
- *
- * @param args A vector of strings containing arguments, returned
from readLine.
- */
- virtual void dispatchCommand(std::vector<std::string> & args) = 0;
-
- /** Read a line from the network and split it into its components.
- *
- * MSN commands and their arguments are separated by white space.
- */
- std::vector<std::string> getLine();
-
- bool isWholeLineAvailable();
- bool bytesAvailable();
-
- /** Write a string to the connection.
- *
- */
- virtual size_t write(std::string s, bool log=true) throw
(std::runtime_error);
-
- /** Write the contents of a stringstream to the connection.
- *
- * @param s The stringstream to write.
- * @param log Should we log this output to the console.
- *
- * write will buffer the output if a connection has not yet been
established.
- * In this case, the data will be written as soon as a connection is
- * established.
- */
- virtual size_t write(std::ostringstream & s, bool log=true) throw
(std::runtime_error);
-
- std::string writeBuffer;
- static std::map<std::string, void
(Connection::*)(std::vector<std::string> &, std::string, std::string)>
messageHandlers;
- void message_plain(std::vector<std::string> & args, std::string mime,
std::string body);
- void message_initial_email_notification(std::vector<std::string> &
args, std::string mime, std::string body);
- void message_email_notification(std::vector<std::string> & args,
std::string mime, std::string body);
- void message_invitation(std::vector<std::string> & args, std::string
mime, std::string body);
- void message_typing_user(std::vector<std::string> & args, std::string
mime, std::string body);
- };
-}
-#endif
Modified: trunk/msn/errorcodes.h
===================================================================
--- trunk/msn/errorcodes.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/errorcodes.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -24,8 +24,6 @@
*/
#include <string>
-#include <list>
-#include <msn/switchboardserver.h>
/** \mainpage libmsn 3.2 Reference
*
Modified: trunk/msn/externals.h
===================================================================
--- trunk/msn/externals.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/externals.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -24,11 +24,16 @@
*/
#include <msn/buddy.h>
+#include <msn/passport.h>
#include <msn/uncopyable.h>
namespace MSN
{
class ListSyncInfo;
+ class NotificationServerConnection;
+ class SwitchboardServerConnection;
+ class Message;
+ class FileTransferInvitation;
class Callbacks : private Uncopyable
{
@@ -38,50 +43,50 @@
virtual void registerSocket(int s, int read, int write) = 0;
virtual void unregisterSocket(int s) = 0;
- virtual void showError(MSN::Connection * conn, std::string msg) = 0;
+ virtual void showError(MSN::Connection * conn, const std::string &
msg) = 0;
- virtual void buddyChangedStatus(MSN::Connection * conn, MSN::Passport
buddy, std::string friendlyname, MSN::BuddyStatus state) = 0;
- virtual void buddyOffline(MSN::Connection * conn, MSN::Passport buddy)
= 0;
+ virtual void buddyChangedStatus(MSN::Connection * conn, const
MSN::Passport & buddy, const std::string & friendlyname, MSN::BuddyStatus
state) = 0;
+ virtual void buddyOffline(MSN::Connection * conn, const MSN::Passport
& buddy) = 0;
- virtual void log(int writing, const char* buf) = 0;
+ virtual void log(int writing, const std::string & message) = 0;
- virtual void gotFriendlyName(MSN::Connection * conn, std::string
friendlyname) = 0;
+ virtual void gotFriendlyName(MSN::Connection * conn, const std::string
& friendlyname) = 0;
virtual void gotBuddyListInfo(MSN::NotificationServerConnection *
conn, MSN::ListSyncInfo * data) = 0;
virtual void gotLatestListSerial(MSN::Connection * conn, int serial) =
0;
virtual void gotGTC(MSN::Connection * conn, char c) = 0;
virtual void gotBLP(MSN::Connection * conn, char c) = 0;
- virtual void gotNewReverseListEntry(MSN::Connection * conn,
MSN::Passport buddy, std::string friendlyname) = 0;
+ virtual void gotNewReverseListEntry(MSN::Connection * conn, const
MSN::Passport & buddy, const std::string & friendlyname) = 0;
- virtual void addedListEntry(MSN::Connection * conn, std::string list,
MSN::Passport buddy, int groupID) = 0;
+ virtual void addedListEntry(MSN::Connection * conn, const std::string
& list, const MSN::Passport & buddy, int groupID) = 0;
- virtual void removedListEntry(MSN::Connection * conn, std::string
list, MSN::Passport buddy, int groupID) = 0;
+ virtual void removedListEntry(MSN::Connection * conn, const
std::string & list, const MSN::Passport & buddy, int groupID) = 0;
- virtual void addedGroup(MSN::Connection * conn, std::string groupName,
int groupID) = 0;
+ virtual void addedGroup(MSN::Connection * conn, const std::string &
groupName, int groupID) = 0;
virtual void removedGroup(MSN::Connection * conn, int groupID) = 0;
- virtual void renamedGroup(MSN::Connection * conn, int groupID,
std::string newGroupName) = 0;
+ virtual void renamedGroup(MSN::Connection * conn, int groupID, const
std::string & newGroupName) = 0;
virtual void gotSwitchboard(MSN::SwitchboardServerConnection * conn,
const void * tag) = 0;
- virtual void buddyJoinedConversation(MSN::SwitchboardServerConnection
* conn, MSN::Passport buddy, std::string friendlyname, int is_initial) = 0;
+ virtual void buddyJoinedConversation(MSN::SwitchboardServerConnection
* conn, const MSN::Passport & buddy, const std::string & friendlyname, int
is_initial) = 0;
- virtual void buddyLeftConversation(MSN::SwitchboardServerConnection *
conn, MSN::Passport buddy) = 0;
+ virtual void buddyLeftConversation(MSN::SwitchboardServerConnection *
conn, const MSN::Passport & buddy) = 0;
- virtual void gotInstantMessage(MSN::SwitchboardServerConnection *
conn, MSN::Passport buddy, std::string friendlyname, MSN::Message * msg) = 0;
+ virtual void gotInstantMessage(MSN::SwitchboardServerConnection *
conn, const MSN::Passport & buddy, const std::string & friendlyname,
MSN::Message * msg) = 0;
virtual void failedSendingMessage(MSN::Connection * conn) = 0;
- virtual void buddyTyping(MSN::Connection * conn, MSN::Passport buddy,
std::string friendlyname) = 0;
+ virtual void buddyTyping(MSN::Connection * conn, const MSN::Passport &
buddy, const std::string & friendlyname) = 0;
virtual void gotInitialEmailNotification(MSN::Connection * conn, int
unread_inbox, int unread_folders) = 0;
- virtual void gotNewEmailNotification(MSN::Connection * conn,
std::string from, std::string subject) = 0;
+ virtual void gotNewEmailNotification(MSN::Connection * conn, const
std::string & from, const std::string & subject) = 0;
- virtual void gotFileTransferInvitation(MSN::Connection * conn,
MSN::Passport buddy, std::string friendlyname, MSN::FileTransferInvitation *
inv) = 0;
+ virtual void gotFileTransferInvitation(MSN::Connection * conn, const
MSN::Passport & buddy, const std::string & friendlyname,
MSN::FileTransferInvitation * inv) = 0;
- virtual void fileTransferProgress(MSN::FileTransferInvitation * inv,
std::string status, unsigned long recv, unsigned long total) = 0;
+ virtual void fileTransferProgress(MSN::FileTransferInvitation * inv,
const std::string & status, unsigned long recv, unsigned long total) = 0;
- virtual void fileTransferFailed(MSN::FileTransferInvitation * inv, int
error, std::string message) = 0;
+ virtual void fileTransferFailed(MSN::FileTransferInvitation * inv, int
error, const std::string & message) = 0;
virtual void fileTransferSucceeded(MSN::FileTransferInvitation * inv)
= 0;
Deleted: trunk/msn/filetransfer.cpp
===================================================================
--- trunk/msn/filetransfer.cpp 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/filetransfer.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,528 +0,0 @@
-/*
- * filetransfer.cpp
- * libmsn
- *
- * Created by Mark Rowe on Wed Mar 17 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <msn/filetransfer.h>
-#include <msn/message.h>
-#include <msn/errorcodes.h>
-#include <msn/externals.h>
-#include <msn/notificationserver.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#else
-#include <winsock.h>
-#include <io.h>
-#endif
-
-#include <cerrno>
-#include <cassert>
-
-namespace MSN
-{
- static const unsigned int MAX_FTP_BLOCK_SIZE = 20000;
-
- void FileTransferInvitation::invitationWasAccepted(const std::string &
body)
- {
- if (this->invitationWasSent())
- {
- this->sendFile(body);
- }
- else
- {
- this->receiveFile(body);
- }
- }
-
- void FileTransferInvitation::invitationWasCanceled(const std::string &
body)
- {
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
0, "Cancelled by remote user");
- if (this->invitationWasSent())
- {
- this->switchboardConnection->invitationsSent.remove(this);
- }
- else
- {
- this->switchboardConnection->invitationsReceived.remove(this);
- }
- this->switchboardConnection->removeFileTransferConnection(this);
- }
-
- void FileTransferInvitation::sendFile(const std::string & msg_body)
- {
- int port = 6891;
- char tmp[64];
- sprintf(tmp, "%d", rand());
- FileTransferConnection * conn = new
FileTransferConnection(this->switchboardConnection->auth.username,
-
std::string(tmp), FileTransferConnection::MSNFTP_SEND, this);
-
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
"Sending IP address", 0, 0);
-
- while((conn->sock =
this->switchboardConnection->myNotificationServer()->externalCallbacks.listenOnPort(port))
< 0)
- {
- port++;
- if (port > 6911)
- {
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
errno, strerror(errno));
- this->switchboardConnection->invitationsSent.remove(this);
- conn->disconnect();
- return;
- }
- }
-
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
1, 0);
-
- this->switchboardConnection->addFileTransferConnection(conn);
-
- std::ostringstream buf_;
- buf_ << "Invitation-Command: ACCEPT\r\n";
- buf_ << "Invitation-Cookie: " << this->cookie << "\r\n";
- buf_ << "IP-Address: " <<
this->switchboardConnection->myNotificationServer()->externalCallbacks.getOurIP()
<< "\r\n";
- buf_ << "Port: " << port << "\r\n";
- buf_ << "AuthCookie: " << conn->auth.cookie << "\r\n";
- buf_ << "Launch-Application: FALSE\r\n";
- buf_ << "Request-Data: IP-Address:\r\n";
- buf_ << "\r\n";
-
- Message * msg = new Message(buf_.str());
- msg->setHeader("Content-Type", "text/x-msmsgsinvite; charset=UTF-8");
- this->switchboardConnection->sendMessage(msg);
- delete msg;
- }
-
- void FileTransferInvitation::receiveFile(const std::string & msg_body)
- {
- Message::Headers headers(msg_body);
- std::string cookie = headers["AuthCookie"];
- std::string remote = headers["IP-Address"];
- std::string port_c = headers["Port"];
- int port;
-
- if (cookie.empty() || remote.empty() || port_c.empty())
- {
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
0, "Missing parameters");
- this->switchboardConnection->invitationsReceived.remove(this);
- return;
- }
-
- port = decimalFromString(port_c);
- FileTransferConnection * conn = new
FileTransferConnection(this->switchboardConnection->auth.username,
- cookie,
FileTransferConnection::MSNFTP_RECV, this);
-
- std::ostringstream buf_;
- buf_ << "Connecting to " << remote << ":" << port << "\n";
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
buf_.str(), 0, 0);
-
- conn->sock =
this->switchboardConnection->myNotificationServer()->externalCallbacks.connectToServer(remote,
port, &conn->connected);
-
- if (conn->sock < 0)
- {
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
errno, strerror(errno));
- this->switchboardConnection->invitationsReceived.remove(this);
- return;
- }
-
- if (! conn->isConnected())
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
0, 1);
- else
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
1, 0);
-
-
this->switchboardConnection->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
"Connected", 0, 0);
- this->switchboardConnection->addFileTransferConnection(conn);
-
- conn->write("VER MSNFTP\r\n");
- }
-
- void FileTransferConnection::disconnect()
- {
- Connection::disconnect();
-
- if (this->auth.fd)
- {
- fclose(this->auth.fd);
- this->auth.fd = NULL;
- }
-
-
this->auth.inv->switchboardConnection->removeFileTransferConnection(this);
- delete this->auth.inv;
- this->auth.inv = NULL;
- }
-
- FileTransferConnection::~FileTransferConnection()
- {
- this->disconnect();
- }
-
- void FileTransferConnection::socketConnectionCompleted()
- {
- Connection::socketConnectionCompleted();
-
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
-
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1,
0);
- }
-
- void FileTransferConnection::socketIsWritable()
- {
- if (this->auth.direction == MSNFTP_SEND)
- this->handleSend();
- }
-
- void FileTransferConnection::dataArrivedOnSocket()
- {
- if (this->auth.direction == MSNFTP_SEND && ! this->auth.connected)
- this->handleSend();
- else
- Connection::dataArrivedOnSocket();
- }
-
- void FileTransferConnection::handleIncomingData()
- {
- if (this->auth.direction == MSNFTP_RECV)
- this->handleReceive();
- else
- this->handleSend();
- }
-
- void FileTransferConnection::handleSend()
- {
- if (! this->auth.connected) // we have not accept()ed yet, but the
read/writability means there's one waiting
- {
- this->handleSend_WaitingForConnection();
- }
- else if (this->auth.fd == NULL)
- {
- this->handleSend_Negotiating();
- }
- else if (this->auth.inv->fileSize != this->auth.bytes_done)
- {
- this->handleSend_Transferring();
- }
- else
- {
- this->handleSend_Bye();
- }
- }
-
- void FileTransferConnection::handleSend_WaitingForConnection()
- {
- int s;
-
- if ((s = accept(this->sock, NULL, NULL)) < 0)
- {
- perror("Could not accept()\n");
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
-
this->auth.inv->switchboardConnection->invitationsSent.remove(this->auth.inv);
- return;
- }
-
-
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
- close(this->sock);
-
- this->sock = s;
-
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1,
0);
-
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Connected", 0, 0);
-
- this->auth.connected = 1;
- this->connected = true;
- }
-
- void FileTransferConnection::handleSend_Negotiating()
- {
- if (! this->isWholeLineAvailable())
- return;
-
- std::vector<std::string> args = this->getLine();
- this->readBuffer =
this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
-
- if (args[0] == "VER")
- {
- if (this->write("VER MSNFTP\r\n") != strlen("VER MSNFTP\r\n"))
- return;
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Negotiating", 0, 0);
- }
- else if (args[0] == "USR")
- {
- if (args[2] != this->auth.cookie) // if they DIFFER
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
-
this->auth.inv->switchboardConnection->invitationsSent.remove(this->auth.inv);
- return;
- }
- std::ostringstream buf_;
- buf_ << "FIL " << this->auth.inv->fileSize << "\r\n";
- this->write(buf_);
- }
- else if (args[0] == "TFR")
- {
- // you asked for it, go to data-dump mode
- this->auth.fd = fopen(this->auth.inv->fileName.c_str(), "r");
- if (this->auth.fd == NULL)
- {
- perror("fopen() failed");
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, "Could not open file for reading");
-
this->auth.inv->switchboardConnection->invitationsSent.remove(this->auth.inv);
- return;
- }
-
- // OK, now we lose control, but the next round of the polling loop
will
- // say that the socket is writable, and then the fun starts...
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Sending data", 0, 0);
-
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
-
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0,
1);
- }
- }
-
- void FileTransferConnection::handleSend_Transferring()
- {
- // just pumping data now
-
- fd_set writefd;
- FD_ZERO(&writefd);
- FD_SET(this->sock, &writefd);
- struct timeval tout={0, 0};
- unsigned char *readBuffer = (unsigned char *)
calloc(MAX_FTP_BLOCK_SIZE, sizeof(unsigned char));
-
- if (select(this->sock + 1, NULL, &writefd, NULL, &tout) == 1)
- {
- int bytesWritten = 0;
- unsigned int blockLength;
- unsigned char blockHeader[3];
- unsigned int bytesRemaining = this->auth.inv->fileSize -
this->auth.bytes_done;
- blockLength = bytesRemaining > MAX_FTP_BLOCK_SIZE / 4 ?
MAX_FTP_BLOCK_SIZE / 4 : bytesRemaining;
- if (blockLength == 0)
- blockHeader[0] = 1;
- else
- blockHeader[0] = 0;
- blockHeader[1] = (blockLength >> 0) & 0xff;
- blockHeader[2] = (blockLength >> 8) & 0xff;
-
- if (this->write(std::string((char *) &blockHeader[bytesWritten], 3
- bytesWritten), false) != 3)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
- goto cleanup;
- }
-
- if (fread(readBuffer, sizeof(unsigned char), blockLength,
this->auth.fd) < 0)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
- goto cleanup;
- }
-
- if ((blockLength = this->write(std::string((char *) readBuffer,
blockLength), false)) < 0)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
- goto cleanup;
- }
- this->auth.bytes_done += blockLength;
- }
- free(readBuffer);
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Sending file", this->auth.bytes_done, this->auth.inv->fileSize);
- return;
-cleanup:
- ;
-
this->auth.inv->switchboardConnection->invitationsSent.remove(this->auth.inv);
- if (readBuffer)
- free(readBuffer);
- if (this->auth.fd)
- {
- fclose(this->auth.fd);
- this->auth.fd = NULL;
- }
- }
-
- void FileTransferConnection::handleSend_Bye()
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
-
-
this->auth.inv->switchboardConnection->invitationsSent.remove(this->auth.inv);
- this->disconnect();
- }
-
-
- void FileTransferConnection::handleReceive()
- {
- if (this->auth.fd == NULL)
- this->handleReceive_Negotiating();
- else
- this->handleReceive_Transferring();
- }
-
- void FileTransferConnection::handleReceive_Negotiating()
- {
- if (! this->isWholeLineAvailable())
- return;
-
- std::vector<std::string> args = this->getLine();
- this->readBuffer =
this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
-
- if (args[0] == "VER")
- {
- std::ostringstream buf_;
- buf_ << "USR " << this->auth.username << " " << this->auth.cookie
<< "\r\n";
- this->write(buf_);
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Negotiating", 0, 0);
- return;
- }
- else if (args[0] == "FIL")
- {
- this->auth.fd = fopen(this->auth.inv->fileName.c_str(), "w");
- if (this->auth.fd == NULL)
- goto error;
-
- this->write("TFR\r\n");
- }
- return;
-error:
- ;
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
-
this->switchboardConnection()->invitationsReceived.remove(this->auth.inv);
- }
-
- void FileTransferConnection::handleReceive_Transferring()
- {
- // Each block has a 3-byte header
- // 0: either 1 or 0. 0 means data block, 1 means transfer completed.
- // 1: Low byte of block length
- // 2: High byte of block length
-
- unsigned int blockLength;
- std::string blockHeader;
-
- while (1)
- {
- if (this->readBuffer.size() < 3)
- return;
-
- // read the three byte header
- blockHeader = this->readBuffer.substr(0, 3);
- if (blockHeader[0] == 1U)
- {
- // Transfer completed block
- if (blockHeader[1] != 0 || blockHeader[2] != 0)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Invalid block header.\n");
- goto cleanup;
- }
- this->write("BYE 16777989\r\n");
-
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
-
- goto cleanup;
- }
- else if (blockHeader[0] != 0U)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Invalid block header.");
- goto cleanup;
- }
-
- // Read the entire block
- blockLength = ((unsigned char) blockHeader[1]) | ((unsigned char)
blockHeader[2]) << 8;
- if (blockLength > MAX_FTP_BLOCK_SIZE)
- {
-
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Block size greater than largest expected block size.");
- goto cleanup;
- }
-
- if (this->readBuffer.size() < 3 + blockLength)
- return;
-
- std::string block = this->readBuffer.substr(3, blockLength);
- this->readBuffer = this->readBuffer.substr(3 + blockLength);
-
- fwrite(block.c_str(), sizeof(unsigned char), block.size(),
this->auth.fd);
- this->auth.bytes_done += blockLength;
-
- if (this->auth.bytes_done == this->auth.inv->fileSize)
- {
- // It appears that sometimes the 1,0,0 block header
- // that indicates success isnt sent...
-
- this->write("BYE 16777989\r\n");
-
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
- goto cleanup;
- }
-
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Receiving file", this->auth.bytes_done, this->auth.inv->fileSize);
- }
- return;
-cleanup:
- ;
-
this->auth.inv->switchboardConnection->invitationsReceived.remove(this->auth.inv);
- if (this->auth.fd)
- {
- fclose(this->auth.fd);
- this->auth.fd = NULL;
- }
- }
-
- void FileTransferInvitation::rejectTransfer()
- {
- std::ostringstream buf_;
- buf_ << "Invitation-Command: CANCEL\r\n";
- buf_ << "Invitation-Cookie: " << this->cookie << "\r\n";
- buf_ << "Cancel-Code: REJECT\r\n";
-
- Message *msg = new Message(buf_.str());
- msg->setHeader("Content-Type", "text/x-msmsgsinvite; charset=UTF-8");
- this->switchboardConnection->sendMessage(msg);
- delete msg;
-
- this->switchboardConnection->invitationsReceived.remove(this);
- }
-
- void FileTransferInvitation::acceptTransfer(const std::string & dest)
- {
- std::ostringstream buf_;
- buf_ << "Invitation-Command: ACCEPT\r\n";
- buf_ << "Invitation-Cookie: " << (this->cookie.empty() ? "" :
this->cookie) << "\r\n";
- buf_ << "Launch-Application: FALSE\r\n";
- buf_ << "Request-Data: IP-Address\r\n";
- buf_ << "\r\n";
-
- this->fileName = dest;
- Message *msg = new Message(buf_.str());
- msg->setHeader("Content-Type", "text/x-msmsgsinvite; charset=UTF-8");
- this->switchboardConnection->sendMessage(msg);
- delete msg;
-
- }
-
- void FileTransferInvitation::cancelTransfer()
- {
- std::ostringstream buf_;
- buf_ << "Invitation-Command: CANCEL\r\n";
- buf_ << "Invitation-Cookie: " << this->cookie << "\r\n";
- buf_ << "Cancel-Code: OUTBANDCANCEL\r\n";
-
- Message *msg = new Message(buf_.str());
- msg->setHeader("Content-Type", "text/x-msmsgsinvite; charset=UTF-8");
- this->switchboardConnection->sendMessage(msg);
- delete msg;
-
- // one of the two below will fail, but it will do so safely and quietly
- this->switchboardConnection->invitationsReceived.remove(this);
- this->switchboardConnection->invitationsSent.remove(this);
-
- this->switchboardConnection->removeFileTransferConnection(this);
- }
-}
Deleted: trunk/msn/filetransfer.h
===================================================================
--- trunk/msn/filetransfer.h 2005-07-11 23:42:29 UTC (rev 358)
+++ trunk/msn/filetransfer.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -1,235 +0,0 @@
-#ifndef __msn_filetransfer_h__
-#define __msn_filetransfer_h__
-
-/*
- * filetransfer.h
- * libmsn
- *
- * Created by Mark Rowe on Wed Mar 17 2004.
- * Copyright (c) 2004 Mark Rowe. All rights reserved.
- *
- * 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
- * (at your option) any later version.
- *
- * 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
- */
-
-#include <msn/util.h>
-#include <msn/switchboardserver.h>
-#include <msn/invitation.h>
-#include <msn/passport.h>
-
-#include <string>
-#include <stdio.h>
-
-namespace MSN
-{
- /** Contains information about the invitation that was sent or received
when
- * a file transfer was initiated.
- */
- class FileTransferInvitation : public Invitation
- {
-public:
- /** The name of the file that is being transferred.
- */
- std::string fileName;
-
- /** The size in bytes of the file that is being transferred.
- */
- long unsigned fileSize;
-
- /** A pointer to user-specified data that can be used to identify this
- * transfer.
- */
- void * userData;
-
- /** Create a new FileTransferInvitation.
- *
- * @todo Do all of these parameters really need to be in the
constructor?
- */
- FileTransferInvitation(Invitation::ApplicationType application_,
std::string cookie_,
- Passport otherUser_, SwitchboardServerConnection *
switchboardConnection_,
- std::string fileName_, long unsigned fileSize_, void
*userData_ = NULL) :
- Invitation(application_, cookie_, otherUser_,
switchboardConnection_),
- fileName(fileName_), fileSize(fileSize_), userData(userData_) {};
-
- FileTransferInvitation(const FileTransferInvitation & invitation_) :
- Invitation(invitation_), fileName(invitation_.fileName),
fileSize(invitation_.fileSize), userData(invitation_.userData) {};
-
- FileTransferInvitation &operator=(const FileTransferInvitation &
invitation_)
- {
- Invitation::operator=(invitation_);
- fileName = invitation_.fileName;
- fileSize = invitation_.fileSize;
- userData = invitation_.userData;
- return *this;
- }
-
- /** The remote side accepted our file transfer. Notify calling code.
- */
- virtual void invitationWasAccepted(const std::string & body);
-
- /** The remote side canceled our file transfer. Notify calling code.
- */
- virtual void invitationWasCanceled(const std::string & body);
-
- /** The user wishes to accept the file transfer, and have the file
- * written to @a destinationFile.
- *
- * @todo Should the received data be passed back to the user to store
- * in the file? This would remove some of the complexity in the
- * file transfer code.
- */
- void acceptTransfer(const std::string & destinationFile);
-
- /** The user wishes to decline the file transfer.
- */
- void rejectTransfer();
-
- /** The user wishes to cancel the file transfer.
- */
- void cancelTransfer();
-private:
- void sendFile(const std::string & msg_body);
- void receiveFile(const std::string & msg_body);
- };
-
-
- /** Represents a connection to another users computer for the purpose of
- * transferring a file.
- *
- * @todo Finish refactoring to store progress explicitly rather than in
- * a complex combination of member variables.
- */
- class FileTransferConnection : public Connection
- {
-public:
-
- /** Are we sending or receiving the file?
- */
- typedef enum
- {
- MSNFTP_SEND,
- MSNFTP_RECV
- } Direction;
-
- /** Are we being connected to or connecting to them?
- */
- typedef enum
- {
- MSNFTP_SERVER,
- MSNFTP_CLIENT
- } Perspective;
-
- /** How far through the process are we?
- */
- typedef enum
- {
- WAITING_FOR_CONNECTION,
- NEGOTIATING,
- TRANSFERRING
- } Progress;
-
- /** AuthData contains authentication information
- * relating to a FileTransferConnection.
- */
- class AuthData : public ::MSN::AuthData
- {
-public:
- /** A string that uniquely identifies this transfer.
- *
- * It is generated during the negotiation of the transfer over the
SwitchboardServerConnection
- */
- std::string cookie;
-
- /** Which direction is the file being sent? */
- Direction direction;
-
- /** Should we serve or connect? */
- Perspective perspective;
-
- /** The invitiation that we are associated with. */
- FileTransferInvitation *inv;
-
- /** The file descriptor that data will be read from or written to
*/
- FILE *fd;
-
- /** Is the transfer connected? */
- bool connected;
-
- /** How many bytes have we transferred? */
- unsigned long bytes_done;
-
- /** Initialize an AuthData instance with the given parameters. */
- AuthData(Passport username_, std::string cookie_, Direction
direction_,
- FileTransferInvitation *inv_=NULL, FILE
*fd_=NULL, bool connected_=false,
- unsigned long bytes_done_=0) :
- ::MSN::AuthData(username_), cookie(cookie_),
direction(direction_),
- perspective((direction == MSNFTP_RECV ? MSNFTP_CLIENT :
MSNFTP_SERVER)), inv(inv_),
- fd(fd_), connected(connected_), bytes_done(bytes_done_) {};
- AuthData(const AuthData & auth_) :
- ::MSN::AuthData(auth_), cookie(auth_.cookie),
direction(auth_.direction),
- perspective(auth_.perspective), inv(auth_.inv),
- fd(auth_.fd), connected(auth_.connected),
bytes_done(auth_.bytes_done) {};
- virtual ~AuthData() { if (fd) fclose(fd); };
-
- AuthData &operator=(const AuthData & auth_)
- {
- ::MSN::AuthData::operator=(auth_);
- cookie = auth_.cookie;
- direction = auth_.direction;
- perspective = auth_.perspective;
- inv = auth_.inv;
- fd = auth_.fd;
- connected = auth_.connected;
- bytes_done = auth_.bytes_done;
- return *this;
- }
- };
-
- /** The AuthData relating to this connection */
- FileTransferConnection::AuthData auth;
-
- /** Initialize this connection with an existing AuthData instance. */
- FileTransferConnection(Passport username_, std::string cookie_,
Direction direction_,
- FileTransferInvitation *inv_=NULL, FILE
*fd_=NULL, bool connected_=false,
- unsigned long bytes_done_=0) :
- Connection(),
- auth(username_, cookie_, direction_, inv_, fd_, connected_,
bytes_done_) {};
- virtual ~FileTransferConnection();
-
- /** @todo Should this really be an empty function? */
- virtual void connect(const std::string & hostname, unsigned int port)
{};
- virtual void disconnect();
-
- virtual void socketIsWritable();
- virtual void socketConnectionCompleted();
- virtual void dataArrivedOnSocket();
- virtual NotificationServerConnection *myNotificationServer() { return
switchboardConnection()->myNotificationServer(); };
-private:
- virtual void handleIncomingData();
- virtual void dispatchCommand(std::vector<std::string> & args) {};
- void handleSend();
- void handleReceive();
-
- void handleSend_WaitingForConnection();
- void handleSend_Negotiating();
- void handleSend_Transferring();
- void handleSend_Bye();
-
- void handleReceive_Negotiating();
- void handleReceive_Transferring();
-
- SwitchboardServerConnection *switchboardConnection() { return
this->auth.inv->switchboardConnection; };
- };
-}
-#endif
Copied: trunk/msn/impl/authdata.h (from rev 356, trunk/msn/authdata.h)
===================================================================
--- trunk/msn/authdata.h 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/authdata.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,40 @@
+/*
+ * authdata.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <string>
+#include <msn/passport.h>
+#include <msn/uncopyable.h>
+
+namespace MSN
+{
+ class AuthData : private Uncopyable
+ {
+public:
+ Passport username;
+
+ AuthData(const Passport & username_) : username(username_) {};
+ AuthData(const AuthData & auth_) : username(auth_.username) {};
+ virtual ~AuthData() {};
+
+ AuthData &operator=(const AuthData & auth_) { username =
auth_.username; return *this; };
+ };
+}
Copied: trunk/msn/impl/buddy.cpp (from rev 356, trunk/msn/buddy.cpp)
===================================================================
--- trunk/msn/buddy.cpp 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/buddy.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,75 @@
+/*
+ * buddy.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Apr 19 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <msn/buddy.h>
+#include "buddy.h"
+#include <cassert>
+
+namespace MSN
+{
+ std::string buddyStatusToString(BuddyStatus state)
+ {
+ switch (state)
+ {
+ case STATUS_AVAILABLE:
+ return "NLN";
+ case STATUS_BUSY:
+ return "BSY";
+ case STATUS_IDLE:
+ return "IDL";
+ case STATUS_BERIGHTBACK:
+ return "BRB";
+ case STATUS_AWAY:
+ return "AWY";
+ case STATUS_ONTHEPHONE:
+ return "PHN";
+ case STATUS_OUTTOLUNCH:
+ return "LUN";
+ case STATUS_INVISIBLE:
+ return "HDN";
+ default:
+ assert(false);
+ }
+ }
+
+ BuddyStatus buddyStatusFromString(std::string state)
+ {
+ if (state == "NLN")
+ return STATUS_AVAILABLE;
+ else if (state == "BSY")
+ return STATUS_BUSY;
+ else if (state == "IDL")
+ return STATUS_IDLE;
+ else if (state == "BRB")
+ return STATUS_BERIGHTBACK;
+ else if (state == "AWY")
+ return STATUS_AWAY;
+ else if (state == "PHN")
+ return STATUS_ONTHEPHONE;
+ else if (state == "LUN")
+ return STATUS_OUTTOLUNCH;
+ else if (state == "HDN")
+ return STATUS_INVISIBLE;
+ else
+ throw std::runtime_error("Unknown status!");
+ }
+}
Copied: trunk/msn/impl/buddy.h (from rev 356, trunk/msn/buddy.h)
===================================================================
--- trunk/msn/buddy.h 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/buddy.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,114 @@
+/*
+ * buddy.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Apr 19 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <string>
+#include <list>
+#include <msn/buddy.h>
+#include <msn/uncopyable.h>
+#include <msn/passport.h>
+
+namespace MSN
+{
+ class Group;
+
+ /** The Buddy class contains information about a member of a buddy list.
+ *
+ * Each Buddy is made up of their passport address (@a userName),
+ * user-visible display name (@a friendlyName), zero or more @a
phoneNumbers,
+ * and zero or more @a groups on the buddy list that they belong to.
+ *
+ * It is only currently used during MSN::Callbacks::gotBuddyListInfo to
+ * store contact information about a buddy that was retrieved during
+ * the buddy list synchronisation process.
+ */
+ class BuddyImpl : private Uncopyable
+ {
+ /** @todo BPR's need to be handled at any time, not just when
syncing. */
+public:
+ /** Their passport address */
+ Passport userName;
+
+ /** Their friendly name */
+ std::string friendlyName;
+
+ /** A list of phone numbers related to this buddy */
+ std::list<Buddy::PhoneNumber> phoneNumbers;
+
+ /** A list of Group's that this buddy is a member of */
+ std::list<Group *> groups;
+
+ /** Initialize the Buddy with the given @a userName_ and @a
friendlyName_ */
+ BuddyImpl(Passport userName_, std::string friendlyName_) :
+ userName(userName_), friendlyName(friendlyName_),
+ phoneNumbers(), groups() {};
+ };
+
+ /** The Group class represents a group of contacts on the buddy list.
+ *
+ * Each group is represented by an integer @a groupID and has a
user-visible
+ * @a name.
+ */
+ class GroupImpl : private Uncopyable
+ {
+public:
+ /** The group ID */
+ int groupID;
+
+ /** The group name */
+ std::string name;
+
+ /** A list of buddies in the group */
+ std::list<Buddy *> buddies;
+
+ /** Initialize a Group with the given @a groupID_ and @a name_ */
+ GroupImpl(int groupID_, std::string name_)
+ : groupID(groupID_), name(name_), buddies() {};
+
+ /** Initialize an empty, invalid group. */
+ GroupImpl() : groupID(-1), name("INVALID"), buddies() {};
+ };
+
+
+ /** The PhoneNumber class contains information about a single phone number
+ * that is retrieved during the buddy list synchronisation process.
+ */
+ class PhoneNumberImpl : private Uncopyable
+ {
+public:
+ /** The name of this phone number.
+ *
+ * @todo Should this be an enumeration containing the possible
+ * types of phone number?
+ */
+ std::string title;
+
+ /** The phone number */
+ std::string number;
+
+ /** @todo Document me! */
+ bool enabled;
+
+ /** Initialize a PhoneNumber with the given @a title_ and phone @a
number_ */
+ PhoneNumberImpl(std::string title_, std::string number_, bool
enabled_=true)
+ : title(title_), number(number_), enabled(enabled_) {};
+ };
+}
Copied: trunk/msn/impl/connection.cpp (from rev 356, trunk/msn/connection.cpp)
===================================================================
--- trunk/msn/connection.cpp 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/connection.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,314 @@
+/*
+ * connection.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include "connection.h"
+#include <msn/errorcodes.h>
+#include <msn/util.h>
+#include <msn/passport.h>
+#include <msn/externals.h>
+#include <msn/notificationserver.h>
+#include <msn/message.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#else
+#include <winsock.h>
+#include <io.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <cerrno>
+#include <time.h>
+#include <cassert>
+
+namespace MSN
+{
+ std::map<std::string, void (ConnectionImpl::*)(std::vector<std::string> &,
std::string, std::string)> ConnectionImpl::messageHandlers;
+ static std::vector<std::string> errors;
+
+ ConnectionImpl::ConnectionImpl()
+ : sock(0), connected(false), trID(1), readBuffer(), writeBuffer()
+ {
+ srand((unsigned int) time(NULL));
+
+ if (errors.size() != 0)
+ {
+ assert(errors.size() == 1000);
+ }
+ else
+ {
+ errors.resize(1000);
+ for (int a = 0; a < 1000; a++)
+ {
+ errors[a] = "Unknown error code";
+ }
+
+ errors[200] = "Syntax error";
+ errors[201] = "Invalid parameter";
+ errors[205] = "Invalid user";
+ errors[206] = "Domain name missing from username";
+ errors[207] = "Already logged in";
+ errors[208] = "Invalid username";
+ errors[209] = "Invalid friendly name";
+ errors[210] = "List full";
+ errors[215] = "This user is already on this list or in this
session";
+ errors[216] = "Not on list";
+ errors[218] = "Already in this mode";
+ errors[219] = "This user is already in the opposite list";
+ errors[280] = "Switchboard server failed";
+ errors[281] = "Transfer notification failed";
+ errors[300] = "Required fields missing";
+ errors[302] = "Not logged in";
+ errors[500] = "Internal server error";
+ errors[501] = "Database server error";
+ errors[510] = "File operation failed at server";
+ errors[520] = "Memory allocation failed on server";
+ errors[600] = "The server is too busy";
+ errors[601] = "The server is unavailable";
+ errors[602] = "A Peer Notification Server is down";
+ errors[603] = "Database connection failed";
+ errors[604] = "Server going down for maintenance";
+ errors[707] = "Server failed to create connection";
+ errors[711] = "Blocking write failed on server";
+ errors[712] = "Session overload on server";
+ errors[713] = "You have been too active recently. Slow down!";
+ errors[714] = "Too many sessions open";
+ errors[715] = "Not expected";
+ errors[717] = "Bad friend file on server";
+ errors[911] = "Authentication failed. Check that you typed your
username and password correctly.";
+ errors[913] = "This action is not allowed while you are offline";
+ errors[920] = "This server is not accepting new users";
+ }
+
+ if (messageHandlers.size() == 0)
+ {
+ messageHandlers["text/plain"] =
&ConnectionImpl::message_plain;
+ messageHandlers["text/x-msmsgsinitialemailnotification"] =
&ConnectionImpl::message_initial_email_notification;
+ messageHandlers["text/x-msmsgsemailnotification"] =
&ConnectionImpl::message_email_notification;
+ messageHandlers["text/x-msmsgsinvite"] =
&ConnectionImpl::message_invitation;
+ messageHandlers["text/x-msmsgscontrol"] =
&ConnectionImpl::message_typing_user;
+ }
+ }
+
+ ConnectionImpl::~ConnectionImpl() {}
+
+ void ConnectionImpl::disconnect()
+ {
+//
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ ::close(this->sock);
+ this->sock = -1;
+ this->writeBuffer.erase();
+ this->readBuffer.erase();
+ this->trID = 1;
+ }
+
+ std::vector<std::string> ConnectionImpl::getLine()
+ {
+ assert(this->isWholeLineAvailable());
+ std::string s = this->readBuffer.substr(0,
this->readBuffer.find("\r\n"));
+// this->myNotificationServer()->externalCallbacks.log(0, (s +
"\n").c_str());
+ return splitString(s, " ");
+ }
+
+ bool ConnectionImpl::isWholeLineAvailable()
+ {
+ return this->readBuffer.find("\r\n") != std::string::npos;
+ }
+
+ void ConnectionImpl::errorOnSocket(int errno_)
+ {
+// this->myNotificationServer()->externalCallbacks.showError(this,
strerror(errno_));
+ this->disconnect();
+ }
+
+ void ConnectionImpl::socketConnectionCompleted()
+ {
+ this->connected = true;
+
+ // We know that we are connected, so this will try writing to the
network.
+ size_t writtenLength = this->write(this->writeBuffer, 1);
+ this->writeBuffer = this->writeBuffer.substr(writtenLength);
+ }
+
+ size_t ConnectionImpl::write(std::string s, bool log) throw
(std::runtime_error)
+ {
+ if (! this->connected)
+ this->writeBuffer.append(s);
+ else
+ {
+// if (log)
+// this->myNotificationServer()->externalCallbacks.log(1,
s.c_str());
+
+ size_t written = 0;
+ while (written < s.size())
+ {
+ size_t newWritten = ::send(this->sock,
s.substr(written).c_str(), (int) (s.size() - written), 0);
+ if (newWritten <= 0)
+ {
+ if (errno == EAGAIN)
+ continue;
+ else
+ break;
+ }
+ written += newWritten;
+ }
+ if (written != s.size())
+ {
+ this->errorOnSocket(errno);
+ return written;
+ }
+ }
+ return s.size();
+ }
+
+ size_t ConnectionImpl::write(std::ostringstream & ss, bool log) throw
(std::runtime_error)
+ {
+ std::string s = ss.str();
+ size_t result = write(s, log);
+ return result;
+ }
+
+ void ConnectionImpl::dataArrivedOnSocket()
+ {
+ char tempReadBuffer[8192];
+ int amountRead = ::recv(this->sock, &tempReadBuffer[0], 8192, 0);
+ if (amountRead < 0)
+ {
+ if (errno == EAGAIN)
+ return;
+
+ // We shouldn't get EAGAIN here because dataArrivedOnSocket
+ // is only called when select/poll etc has told us that
+ // the socket is readable.
+ // assert(errno != EAGAIN);
+
+// this->myNotificationServer()->externalCallbacks.showError(this,
strerror(errno));
+ this->disconnect();
+ }
+ else if (amountRead == 0)
+ {
+// this->myNotificationServer()->externalCallbacks.showError(this,
"Connection closed by remote endpoint.");
+ this->disconnect();
+ }
+ else
+ {
+ this->readBuffer += std::string(tempReadBuffer, amountRead);
+ try
+ {
+ handleIncomingData();
+ }
+ catch (std::exception & e)
+ {
+//
this->myNotificationServer()->externalCallbacks.showError(this, e.what());
+ }
+ }
+ }
+
+ void ConnectionImpl::handle_MSG(std::vector<std::string> & args)
+ {
+ int msglen;
+ std::string msg;
+ std::string mime;
+ std::string body;
+ size_t tmp;
+
+ msglen = decimalFromString(args[3]);
+ msg = this->readBuffer.substr(0, msglen);
+ this->readBuffer = this->readBuffer.substr(msglen);
+
+ body = msg.substr(msg.find("\r\n\r\n") + 4);
+ mime = msg.substr(0, msg.size() - body.size());
+
+ std::string contentType;
+ Message::Headers headers(mime);
+ contentType = headers["Content-Type"];
+
+ if ((tmp = contentType.find("; charset")) != std::string::npos)
+ contentType = contentType.substr(0, tmp);
+
+ std::map<std::string, void
(ConnectionImpl::*)(std::vector<std::string> &, std::string,
std::string)>::iterator i = messageHandlers.find(contentType);
+ if (i != messageHandlers.end())
+ (this->*(messageHandlers[contentType]))(args, mime, body);
+ }
+
+ void ConnectionImpl::message_plain(std::vector<std::string> & args,
std::string mime, std::string body)
+ {
+ Message msg(body, mime);
+
+//
this->myNotificationServer()->externalCallbacks.gotInstantMessage(static_cast<SwitchboardServerConnection
*>(this),
+// args[1], decodeURL(args[2]), &msg);
+ }
+
+ void
ConnectionImpl::message_initial_email_notification(std::vector<std::string> &
args, std::string mime, std::string body)
+ {
+ std::string unreadInbox;
+ std::string unreadFolder;
+ int unreadInboxCount = 0, unreadFolderCount = 0;
+
+ // Initial email notifications body is a set of MIME headers
+ Message::Headers headers(body);
+
+ unreadInbox = headers["Inbox-Unread"];
+ unreadFolder = headers["Folders-Unread"];
+ if (! unreadInbox.empty())
+ unreadInboxCount = decimalFromString(unreadInbox);
+
+ if (! unreadFolder.empty())
+ unreadFolderCount = decimalFromString(unreadFolder);
+
+//
this->myNotificationServer()->externalCallbacks.gotInitialEmailNotification(this,
unreadInboxCount, unreadFolderCount);
+ }
+
+
+ void ConnectionImpl::message_email_notification(std::vector<std::string> &
args, std::string mime, std::string body)
+ {
+ // New email notifications body is a set of MIME headers
+ Message::Headers headers(body);
+
+ std::string from = headers["From-Addr"];
+ std::string subject = headers["Subject"];
+
+//
this->myNotificationServer()->externalCallbacks.gotNewEmailNotification(this,
from, subject);
+ }
+
+
+ void ConnectionImpl::message_invitation(std::vector<std::string> & args,
std::string mime, std::string body)
+ {
+// static_cast<SwitchboardServerConnection
*>(this)->handleInvite(args[1], decodeURL(args[2]), mime, body);
+ }
+
+ void ConnectionImpl::message_typing_user(std::vector<std::string> & args,
std::string mime, std::string body)
+ {
+// this->myNotificationServer()->externalCallbacks.buddyTyping(this,
args[1], decodeURL(args[2]));
+ }
+
+ void ConnectionImpl::showError(int errorCode)
+ {
+ std::ostringstream buf_;
+ buf_ << "Error code: " << errorCode << " (" << errors[errorCode] <<
")";
+// this->myNotificationServer()->externalCallbacks.showError(this,
buf_.str());
+ }
+}
Copied: trunk/msn/impl/connection.h (from rev 356, trunk/msn/connection.h)
===================================================================
--- trunk/msn/connection.h 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/connection.h 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,181 @@
+/*
+ * connection.h
+ * libmsn
+ *
+ * Created by Mark Rowe on Mon Mar 22 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <msn/uncopyable.h>
+#include <msn/connection.h>
+#include "sstream_fix.h"
+#include <stdexcept>
+
+namespace MSN
+{
+ class callback;
+ class Message;
+ class Passport;
+ class NotificationServerConnection;
+ class SwitchboardServerConnection;
+ class FileTransferConnection;
+ class FileTransferInvitation;
+
+ /** An abstract base class that represents a connection to another
computer.
+ *
+ * Connection provides an interface and some functionality that is common
+ * to notification, switchboard and file transfer connections.
+ *
+ * @todo Connection should have a read buffer that stores all incoming data
+ * that is waiting to be processed. Member functions should use that
+ * for necessary data, and <em>not</em> call Connection::readExactly.
+ */
+ class ConnectionImpl : private Uncopyable
+ {
+ friend class SwitchboardServerConnection;
+ friend class NotificationServerConnection;
+ friend class FileTransferConnection;
+ friend class FileTransferInvitation;
+
+public:
+ /** The socket which connects this Connection to another computer
+ *
+ * @deprecated In the future, this member will be made private. Any
+ * functions that access this member should be converted
to
+ * member functions of a subclass.
+ */
+ int sock;
+
+ /** Indicates whether a connection has been established.
+ *
+ * @todo This is currently public only because
FileTransferInvitation::receiveFile
+ * accesses it. It should be made protected in the future, and
+ * FileTransferInvitation refactored to remove it's dependency
on
+ * this attribute.
+ */
+ bool connected;
+
+private:
+ /** The transaction ID of the next command to be sent.
+ */
+ int trID;
+
+ std::string readBuffer;
+public:
+ ConnectionImpl();
+ virtual ~ConnectionImpl();
+
+ /** Connect ourself to @a hostname on @a port.
+ */
+ virtual void connect(const std::string & hostname, unsigned int port)
= 0;
+
+ /** Close the current connection.
+ *
+ * This should not be called if the connection is already disconnected.
+ */
+ virtual void disconnect() = 0;
+
+ /** @name External Socket Hooks
+ *
+ * These members should be called whenever an appropriate socket event
+ * occurs.
+ */
+ /** @{ */
+
+ /** New data is available on the connection.
+ */
+ virtual void dataArrivedOnSocket();
+
+ /** The connection has been established.
+ */
+ virtual void socketConnectionCompleted();
+
+ /** The socket is ready for data to be written to it.
+ */
+ virtual void socketIsWritable() {};
+
+ /** An error has occurred on the socket.
+ */
+ virtual void errorOnSocket(int errno_);
+ /** @} */
+
+ /** Notify the calling library that an error with code @a errorCode has
+ * occured.
+ */
+ void showError(int errorCode);
+
+ /** Is this Connection connected to a remote endpoint?
+ */
+ bool isConnected() { return this->connected; };
+
+ /** Retrieve the parent NotificationServerConnection from this
connection */
+ virtual NotificationServerConnection *myNotificationServer() = 0;
+private:
+ /** Process a @c <code>MSG</code> command.
+ *
+ * This method will read the remaining message data from the network
+ * and then delegates to private @c message_* functions based on the
+ * @c Content-Type header found in the message.
+ */
+ void handle_MSG(std::vector<std::string> & args);
+
+ virtual void handleIncomingData() = 0;
+
+ /** Dispatch a command to its appropriate handler routines based on @a
args.
+ *
+ * @param args A vector of strings containing arguments, returned
from readLine.
+ */
+ virtual void dispatchCommand(std::vector<std::string> & args) = 0;
+
+ /** Read a line from the network and split it into its components.
+ *
+ * MSN commands and their arguments are separated by white space.
+ */
+ std::vector<std::string> getLine();
+
+ bool isWholeLineAvailable();
+ bool bytesAvailable();
+
+ /** Write a string to the connection.
+ *
+ */
+ virtual size_t write(std::string s, bool log=true) throw
(std::runtime_error);
+
+ /** Write the contents of a stringstream to the connection.
+ *
+ * @param s The stringstream to write.
+ * @param log Should we log this output to the console.
+ *
+ * write will buffer the output if a connection has not yet been
established.
+ * In this case, the data will be written as soon as a connection is
+ * established.
+ */
+ virtual size_t write(std::ostringstream & s, bool log=true) throw
(std::runtime_error);
+
+ std::string writeBuffer;
+ static std::map<std::string, void
(ConnectionImpl::*)(std::vector<std::string> &, std::string, std::string)>
messageHandlers;
+ void message_plain(std::vector<std::string> & args, std::string mime,
std::string body);
+ void message_initial_email_notification(std::vector<std::string> &
args, std::string mime, std::string body);
+ void message_email_notification(std::vector<std::string> & args,
std::string mime, std::string body);
+ void message_invitation(std::vector<std::string> & args, std::string
mime, std::string body);
+ void message_typing_user(std::vector<std::string> & args, std::string
mime, std::string body);
+ };
+}
Copied: trunk/msn/impl/filetransfer.cpp (from rev 356,
trunk/msn/filetransfer.cpp)
===================================================================
--- trunk/msn/filetransfer.cpp 2005-07-11 23:24:29 UTC (rev 356)
+++ trunk/msn/impl/filetransfer.cpp 2005-07-12 03:08:54 UTC (rev 359)
@@ -0,0 +1,531 @@
+/*
+ * filetransfer.cpp
+ * libmsn
+ *
+ * Created by Mark Rowe on Wed Mar 17 2004.
+ * Copyright (c) 2004 Mark Rowe. All rights reserved.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#include <msn/filetransfer.h>
+#include "filetransfer.h"
+#include <msn/message.h>
+#include <msn/errorcodes.h>
+#include <msn/externals.h>
+#include <msn/notificationserver.h>
+#include <msn/switchboardserver.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#else
+#include <winsock.h>
+#include <io.h>
+#endif
+
+#include <sstream>
+#include <cerrno>
+#include <cassert>
+
+namespace MSN
+{
+ static const unsigned int MAX_FTP_BLOCK_SIZE = 20000;
+
+ void FileTransferInvitationImpl::invitationWasAccepted(const std::string &
body)
+ {
+ if (this->invitationWasSent())
+ {
+ this->sendFile(body);
+ }
+ else
+ {
+ this->receiveFile(body);
+ }
+ }
+
+ void FileTransferInvitationImpl::invitationWasCanceled(const std::string &
body)
+ {
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
0, "Cancelled by remote user");
+ if (this->invitationWasSent())
+ {
+// this->switchboardConnection()->invitationsSent.remove(this);
+ }
+ else
+ {
+// this->switchboardConnection()->invitationsReceived.remove(this);
+ }
+// this->switchboardConnection()->removeFileTransferConnection(this);
+ }
+
+ void FileTransferInvitationImpl::sendFile(const std::string & msg_body)
+ {
+ int port = 6891;
+ char tmp[64];
+ sprintf(tmp, "%d", rand());
+// FileTransferConnection * conn = new
FileTransferConnection(this->switchboardConnection()->auth.username,
+//
std::string(tmp), FileTransferConnectionImpl::MSNFTP_SEND, this);
+
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
"Sending IP address", 0, 0);
+
+// while((conn->sock =
this->switchboardConnection()->myNotificationServer()->externalCallbacks.listenOnPort(port))
< 0)
+ {
+ port++;
+ if (port > 6911)
+ {
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
errno, strerror(errno));
+// this->switchboardConnection()->invitationsSent.remove(this);
+// conn->disconnect();
+ return;
+ }
+ }
+
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
1, 0);
+
+// this->switchboardConnection()->addFileTransferConnection(conn);
+
+ std::ostringstream buf_;
+ buf_ << "Invitation-Command: ACCEPT\r\n";
+ buf_ << "Invitation-Cookie: " << this->cookie << "\r\n";
+// buf_ << "IP-Address: " <<
this->switchboardConnection()->myNotificationServer()->externalCallbacks.getOurIP()
<< "\r\n";
+ buf_ << "Port: " << port << "\r\n";
+// buf_ << "AuthCookie: " << conn->auth.cookie << "\r\n";
+ buf_ << "Launch-Application: FALSE\r\n";
+ buf_ << "Request-Data: IP-Address:\r\n";
+ buf_ << "\r\n";
+
+ Message * msg = new Message(buf_.str());
+ msg->setHeader("Content-Type", "text/x-msmsgsinvite; charset=UTF-8");
+// this->switchboardConnection()->sendMessage(msg);
+ delete msg;
+ }
+
+ void FileTransferInvitationImpl::receiveFile(const std::string & msg_body)
+ {
+ Message::Headers headers(msg_body);
+ std::string cookie = headers["AuthCookie"];
+ std::string remote = headers["IP-Address"];
+ std::string port_c = headers["Port"];
+ int port;
+
+ if (cookie.empty() || remote.empty() || port_c.empty())
+ {
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
0, "Missing parameters");
+// this->switchboardConnection()->invitationsReceived.remove(this);
+ return;
+ }
+
+ port = decimalFromString(port_c);
+// FileTransferConnection * conn = new
FileTransferConnection(this->switchboardConnection()->auth.username,
+// cookie,
FileTransferConnectionImpl::MSNFTP_RECV, this);
+
+ std::ostringstream buf_;
+ buf_ << "Connecting to " << remote << ":" << port << "\n";
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
buf_.str(), 0, 0);
+
+// conn->sock =
this->switchboardConnection()->myNotificationServer()->externalCallbacks.connectToServer(remote,
port, &conn->connected);
+
+// if (conn->sock < 0)
+ {
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferFailed(this,
errno, strerror(errno));
+// this->switchboardConnection()->invitationsReceived.remove(this);
+ return;
+ }
+
+// if (! conn->isConnected())
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
0, 1);
+// else
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.registerSocket(conn->sock,
1, 0);
+
+//
this->switchboardConnection()->myNotificationServer()->externalCallbacks.fileTransferProgress(this,
"Connected", 0, 0);
+// this->switchboardConnection()->addFileTransferConnection(conn);
+
+// conn->write("VER MSNFTP\r\n");
+ }
+
+ void FileTransferConnectionImpl::disconnect()
+ {
+ // self_.ConnectionImpl::disconnect();
+
+// if (this->auth.fd)
+ {
+// fclose(this->auth.fd);
+// this->auth.fd = NULL;
+ }
+
+//
this->auth.inv->switchboardConnection()->removeFileTransferConnection(this);
+// delete this->auth.inv;
+// this->auth.inv = NULL;
+ }
+
+ FileTransferConnectionImpl::~FileTransferConnection()
+ {
+ this->disconnect();
+ }
+
+ void FileTransferConnectionImpl::socketConnectionCompleted()
+ {
+// self_.ConnectionImpl::socketConnectionCompleted();
+//
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+//
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1,
0);
+ }
+
+ void FileTransferConnectionImpl::socketIsWritable()
+ {
+// if (this->auth.direction == MSNFTP_SEND)
+// this->handleSend();
+ }
+
+ void FileTransferConnectionImpl::dataArrivedOnSocket()
+ {
+// if (this->auth.direction == MSNFTP_SEND && ! this->auth.connected)
+// this->handleSend();
+// else
+// self_.ConnectionImpl::dataArrivedOnSocket();
+ }
+
+ void FileTransferConnectionImpl::handleIncomingData()
+ {
+// if (this->auth.direction == MSNFTP_RECV)
+// this->handleReceive();
+// else
+// this->handleSend();
+ }
+
+ void FileTransferConnectionImpl::handleSend()
+ {
+// if (! this->auth.connected) // we have not accept()ed yet, but the
read/writability means there's one waiting
+// {
+// this->handleSend_WaitingForConnection();
+// }
+// else if (this->auth.fd == NULL)
+// {
+// this->handleSend_Negotiating();
+// }
+// else if (this->auth.inv->fileSize != this->auth.bytes_done)
+// {
+// this->handleSend_Transferring();
+// }
+// else
+ {
+ this->handleSend_Bye();
+ }
+ }
+
+ void FileTransferConnectionImpl::handleSend_WaitingForConnection()
+ {
+ int s;
+
+ if ((s = accept(this->sock, NULL, NULL)) < 0)
+ {
+ perror("Could not accept()\n");
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+//
this->auth.inv->switchboardConnection()->invitationsSent.remove(this->auth.inv);
+ return;
+ }
+
+//
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+ close(this->sock);
+
+ this->sock = s;
+//
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 1,
0);
+
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Connected", 0, 0);
+
+// this->auth.connected = 1;
+ this->connected = true;
+ }
+
+ void FileTransferConnectionImpl::handleSend_Negotiating()
+ {
+// if (! this->isWholeLineAvailable())
+// return;
+
+// std::vector<std::string> args = this->getLine();
+// this->readBuffer =
this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
+
+// if (args[0] == "VER")
+ {
+// if (this->write("VER MSNFTP\r\n") != strlen("VER MSNFTP\r\n"))
+// return;
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Negotiating", 0, 0);
+ }
+// else if (args[0] == "USR")
+ {
+// if (args[2] != this->auth.cookie) // if they DIFFER
+ {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+//
this->auth.inv->switchboardConnection()->invitationsSent.remove(this->auth.inv);
+ return;
+ }
+ std::ostringstream buf_;
+// buf_ << "FIL " << this->auth.inv->fileSize << "\r\n";
+// this->write(buf_);
+ }
+// else if (args[0] == "TFR")
+ {
+ // you asked for it, go to data-dump mode
+// this->auth.fd = fopen(this->auth.inv->fileName.c_str(), "r");
+// if (this->auth.fd == NULL)
+ {
+ perror("fopen() failed");
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, "Could not open file for reading");
+//
this->auth.inv->switchboardConnection()->invitationsSent.remove(this->auth.inv);
+ return;
+ }
+
+ // OK, now we lose control, but the next round of the polling loop
will
+ // say that the socket is writable, and then the fun starts...
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Sending data", 0, 0);
+//
this->myNotificationServer()->externalCallbacks.unregisterSocket(this->sock);
+//
this->myNotificationServer()->externalCallbacks.registerSocket(this->sock, 0,
1);
+ }
+ }
+
+ void FileTransferConnectionImpl::handleSend_Transferring()
+ {
+ // just pumping data now
+
+ fd_set writefd;
+ FD_ZERO(&writefd);
+ FD_SET(this->sock, &writefd);
+ struct timeval tout={0, 0};
+ unsigned char *readBuffer = (unsigned char *)
calloc(MAX_FTP_BLOCK_SIZE, sizeof(unsigned char));
+
+ if (select(this->sock + 1, NULL, &writefd, NULL, &tout) == 1)
+ {
+ int bytesWritten = 0;
+ unsigned int blockLength;
+ unsigned char blockHeader[3];
+// unsigned int bytesRemaining = this->auth.inv->fileSize -
this->auth.bytes_done;
+// blockLength = bytesRemaining > MAX_FTP_BLOCK_SIZE / 4 ?
MAX_FTP_BLOCK_SIZE / 4 : bytesRemaining;
+ if (blockLength == 0)
+ blockHeader[0] = 1;
+ else
+ blockHeader[0] = 0;
+ blockHeader[1] = (blockLength >> 0) & 0xff;
+ blockHeader[2] = (blockLength >> 8) & 0xff;
+
+// if (this->write(std::string((char *) &blockHeader[bytesWritten],
3 - bytesWritten), false) != 3)
+// {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+// goto cleanup;
+// }
+
+// if (fread(readBuffer, sizeof(unsigned char), blockLength,
this->auth.fd) < 0)
+// {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+// goto cleanup;
+// }
+
+// if ((blockLength = this->write(std::string((char *) readBuffer,
blockLength), false)) < 0)
+// {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+// goto cleanup;
+// }
+// this->auth.bytes_done += blockLength;
+ }
+ free(readBuffer);
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Sending file", this->auth.bytes_done, this->auth.inv->fileSize);
+ return;
+cleanup:
+ ;
+//
this->auth.inv->switchboardConnection()->invitationsSent.remove(this->auth.inv);
+ if (readBuffer)
+ free(readBuffer);
+// if (this->auth.fd)
+// {
+// fclose(this->auth.fd);
+// this->auth.fd = NULL;
+// }
+ }
+
+ void FileTransferConnectionImpl::handleSend_Bye()
+ {
+//
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
+
+//
this->auth.inv->switchboardConnection()->invitationsSent.remove(this->auth.inv);
+ this->disconnect();
+ }
+
+
+ void FileTransferConnectionImpl::handleReceive()
+ {
+// if (this->auth.fd == NULL)
+// this->handleReceive_Negotiating();
+// else
+// this->handleReceive_Transferring();
+ }
+
+ void FileTransferConnectionImpl::handleReceive_Negotiating()
+ {
+// if (! this->isWholeLineAvailable())
+// return;
+
+// std::vector<std::string> args = this->getLine();
+// this->readBuffer =
this->readBuffer.substr(this->readBuffer.find("\r\n") + 2);
+
+// if (args[0] == "VER")
+ {
+ std::ostringstream buf_;
+// buf_ << "USR " << this->auth.username << " " <<
this->auth.cookie << "\r\n";
+// this->write(buf_);
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Negotiating", 0, 0);
+ return;
+ }
+// else if (args[0] == "FIL")
+ {
+// this->auth.fd = fopen(this->auth.inv->fileName.c_str(), "w");
+// if (this->auth.fd == NULL)
+// goto error;
+
+// this->write("TFR\r\n");
+ }
+ return;
+error:
+ ;
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
errno, strerror(errno));
+//
this->switchboardConnection()->invitationsReceived.remove(this->auth.inv);
+ }
+
+ void FileTransferConnectionImpl::handleReceive_Transferring()
+ {
+ // Each block has a 3-byte header
+ // 0: either 1 or 0. 0 means data block, 1 means transfer completed.
+ // 1: Low byte of block length
+ // 2: High byte of block length
+
+ unsigned int blockLength;
+ std::string blockHeader;
+
+ while (1)
+ {
+// if (this->readBuffer.size() < 3)
+// return;
+
+ // read the three byte header
+// blockHeader = this->readBuffer.substr(0, 3);
+ if (blockHeader[0] == 1U)
+ {
+ // Transfer completed block
+ if (blockHeader[1] != 0 || blockHeader[2] != 0)
+ {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Invalid block header.\n");
+ goto cleanup;
+ }
+// this->write("BYE 16777989\r\n");
+//
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
+
+ goto cleanup;
+ }
+ else if (blockHeader[0] != 0U)
+ {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Invalid block header.");
+ goto cleanup;
+ }
+
+ // Read the entire block
+ blockLength = ((unsigned char) blockHeader[1]) | ((unsigned char)
blockHeader[2]) << 8;
+ if (blockLength > MAX_FTP_BLOCK_SIZE)
+ {
+//
this->myNotificationServer()->externalCallbacks.fileTransferFailed(this->auth.inv,
0, "Block size greater than largest expected block size.");
+ goto cleanup;
+ }
+
+// if (this->readBuffer.size() < 3 + blockLength)
+// return;
+
+// std::string block = this->readBuffer.substr(3, blockLength);
+// this->readBuffer = this->readBuffer.substr(3 + blockLength);
+
+// fwrite(block.c_str(), sizeof(unsigned char), block.size(),
this->auth.fd);
+// this->auth.bytes_done += blockLength;
+
+// if (this->auth.bytes_done == this->auth.inv->fileSize)
+ {
+ // It appears that sometimes the 1,0,0 block header
+ // that indicates success isnt sent...
+
+// this->write("BYE 16777989\r\n");
+//
this->myNotificationServer()->externalCallbacks.fileTransferSucceeded(this->auth.inv);
+ goto cleanup;
+ }
+//
this->myNotificationServer()->externalCallbacks.fileTransferProgress(this->auth.inv,
"Receiving file", this->auth.bytes_done, this->auth.inv->fileSize);
+ }
+ return;
+cleanup:
+ ;
+//
this->auth.inv->switchboardConnection()->invitationsReceived.remove(this->auth.inv);
+// if (this->auth.fd)
+ {
+// fclose(this->auth.fd);
+// this->auth.fd = NULL;
+ }
+ }
+
+ void FileTransfe |