You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.4 KiB
171 lines
3.4 KiB
/*
|
|
|
|
NetworkConnection
|
|
|
|
High level socket instance wrapper
|
|
|
|
Author:
|
|
|
|
Philip Lindsay <follower@rancidbacon.com>
|
|
|
|
License:
|
|
|
|
Copyright 2007-2008 // LGPL
|
|
|
|
*/
|
|
|
|
#include "connection.h"
|
|
|
|
int NetworkConnection::_nextSocket = 0;
|
|
|
|
|
|
NetworkConnection::NetworkConnection(uint16_t port) {
|
|
/*
|
|
|
|
Create the low-level socket this instance wraps (for server connections).
|
|
|
|
*/
|
|
_socket = _nextSocket; // TODO: Do properly (& max)
|
|
_nextSocket++;
|
|
socket(_socket, Sn_MR_TCP, port, 0);
|
|
}
|
|
|
|
|
|
NetworkConnection::NetworkConnection() {
|
|
/*
|
|
|
|
Create the low-level socket this instance wraps (for client connections).
|
|
|
|
*/
|
|
NetworkConnection(0);
|
|
}
|
|
|
|
|
|
int NetworkConnection::listen() { // TODO: Make private or protected?
|
|
/*
|
|
|
|
Start listening for a connection from a client.
|
|
|
|
*/
|
|
return !!::listen(_socket); // TODO: Use C++ namespaces for the driver functions?
|
|
}
|
|
|
|
|
|
int NetworkConnection::connect(uint8 * addr, uint16 port) { // TODO: Make private or protected?
|
|
/*
|
|
|
|
Client connection to a server.
|
|
|
|
*/
|
|
|
|
// TODO: Accept bytes here for addr?
|
|
int result = 0;
|
|
|
|
result = !!::connect(_socket, addr, port); // TODO: Use C++ namespaces for the driver functions?
|
|
return result;
|
|
}
|
|
|
|
|
|
int NetworkConnection::available() {
|
|
/*
|
|
|
|
Functionality matches 'Serial.available()'.
|
|
|
|
Note: If the socket is not connected then this will return 0,
|
|
but it is intended that 'isConnected()' would be checked first.
|
|
|
|
Returns:
|
|
"The number of bytes available to read ... or 0 if none are available.
|
|
If any data has come in, [...].available() will be greater than 0."
|
|
|
|
*/
|
|
// TODO: Do we want to check for 'isConnected' as well, or not?
|
|
// We have to, I guess, for valid behaviour with 'getSn_*'.
|
|
if (!isConnected()) {
|
|
return 0;
|
|
}
|
|
|
|
return getSn_RX_RSR(_socket);
|
|
}
|
|
|
|
|
|
#define NO_READ_DATA_AVAILABLE -1
|
|
|
|
int NetworkConnection::read() {
|
|
/*
|
|
|
|
Functionality matches 'Serial.read()'.
|
|
|
|
Returns:
|
|
"an int, the first byte of incoming serial data available
|
|
(or -1 if no data is available)."
|
|
|
|
|
|
Note: I thought 'recv' blocked until data was available,
|
|
but it currently seems not to block after all.
|
|
However, because I'm seeking to match the 'Serial.read'
|
|
behaviour we don't actually want to block anyway,
|
|
so we'll ignore it for the moment and handle things
|
|
ourself for now.
|
|
|
|
*/
|
|
uint8_t theByte;
|
|
|
|
if (!available()) {
|
|
return NO_READ_DATA_AVAILABLE;
|
|
}
|
|
|
|
recv(_socket, &theByte, 1);
|
|
return theByte;
|
|
}
|
|
|
|
|
|
int NetworkConnection::isConnected() {
|
|
/*
|
|
|
|
Returns true if the connection is established.
|
|
|
|
*/
|
|
// TODO: If we want the 'Network*' classes to be generic we
|
|
// would need to handle this differently:
|
|
return (getSn_SR(_socket) == SOCK_ESTABLISHED);
|
|
}
|
|
|
|
|
|
void NetworkConnection::print(uint8_t b) {
|
|
/*
|
|
|
|
Send a character over connection. Naming matches 'Serial' API.
|
|
|
|
*/
|
|
if (isConnected()) {
|
|
send(_socket, &b, 1);
|
|
} else {
|
|
// Just drop it if we're not connected.
|
|
}
|
|
}
|
|
|
|
|
|
void NetworkConnection::print(const char * text) {
|
|
/*
|
|
|
|
Send a string over connection. Naming matches 'Serial' API.
|
|
|
|
*/
|
|
for (unsigned int idx = 0; idx < strlen(text); idx++) {
|
|
print(text[idx]);
|
|
}
|
|
}
|
|
|
|
void NetworkConnection::close() {
|
|
/*
|
|
|
|
Close the connection.
|
|
|
|
*/
|
|
// TODO: Determine if we need/want the disconnect (see pg 26 W5100)
|
|
::close(_socket);
|
|
disconnect(_socket);
|
|
}
|
|
|