241 lines
6.9 KiB
C#
241 lines
6.9 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
namespace Microsoft.Singularity.Smtp
|
|
{
|
|
public class Session
|
|
{
|
|
private Socket socket;
|
|
private byte[] ibuf;
|
|
private int iend;
|
|
private int ibeg;
|
|
private byte[] obuf;
|
|
private int odata;
|
|
private int result;
|
|
private bool verbose;
|
|
|
|
public Session(Socket socket)
|
|
{
|
|
this.socket = socket;
|
|
this.ibuf = new byte [4096];
|
|
this.ibeg = 0;
|
|
this.iend = 0;
|
|
this.obuf = new byte [4096];
|
|
this.odata = 0;
|
|
this.result = 0;
|
|
this.verbose = true;
|
|
}
|
|
|
|
private int HaveLine()
|
|
{
|
|
int left = iend - ibeg;
|
|
for (int i = 0; i + 1< left; i++) {
|
|
if (ibuf[ibeg + i] == '\r' && ibuf[ibeg + i + 1] == '\n') {
|
|
// return the # of character (not \r\n) in line.
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
private int ReadLine()
|
|
{
|
|
for (;;) {
|
|
if (ibeg < iend) {
|
|
|
|
// See if there is a line already in the buffer.
|
|
int line = HaveLine();
|
|
if (line >= 0) {
|
|
return line;
|
|
}
|
|
|
|
// Make sure the remaining data is at the start of buffer.
|
|
if (ibeg > 0) {
|
|
Array.Copy(ibuf, ibeg, ibuf, 0, iend - ibeg);
|
|
iend -= ibeg;
|
|
ibeg = 0;
|
|
}
|
|
}
|
|
else {
|
|
ibeg = 0;
|
|
iend = 0;
|
|
}
|
|
|
|
int read = socket.Receive(ibuf, iend, ibuf.Length - iend, SocketFlags.None);
|
|
if (read == 0) {
|
|
// Should probably throw an exception.
|
|
return -1;
|
|
}
|
|
iend += read;
|
|
}
|
|
}
|
|
|
|
public int Result
|
|
{
|
|
get { return result; }
|
|
}
|
|
|
|
public bool Verbose
|
|
{
|
|
get { return verbose; }
|
|
set { verbose = value; }
|
|
}
|
|
|
|
public string ReadLine7()
|
|
{
|
|
result = 0;
|
|
int line = ReadLine();
|
|
if (line >= 0) {
|
|
string data = Encoding.ASCII.GetString(ibuf, ibeg, line);
|
|
for (int i = 0; i < line && ibuf[ibeg + i] >= '0' && ibuf[ibeg + i] <= '9'; i++) {
|
|
result = result * 10 + (ibuf[ibeg + i] - '0');
|
|
}
|
|
ibeg += line + 2;
|
|
if (verbose) {
|
|
Console.WriteLine("S: {0}", data);
|
|
}
|
|
return data;
|
|
}
|
|
if (verbose) {
|
|
Console.WriteLine("S: <end>");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public int ReadLine8(byte[] buffer, int offset)
|
|
{
|
|
result = 0;
|
|
int line = ReadLine();
|
|
if (line >= 0) {
|
|
Array.Copy(ibuf, ibeg, buffer, offset, line);
|
|
ibeg += line + 2;
|
|
if (verbose) {
|
|
Console.WriteLine("S: <8bit>");
|
|
}
|
|
return line;
|
|
}
|
|
if (verbose) {
|
|
Console.WriteLine("S: <end>");
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public void WritePrefix(byte prefix)
|
|
{
|
|
obuf[odata++] = prefix;
|
|
}
|
|
|
|
public void WriteLine7(string line)
|
|
{
|
|
WriteLine7(line, null, null);
|
|
}
|
|
|
|
public void WriteLine7(string a, string b)
|
|
{
|
|
WriteLine7(a, b, null);
|
|
}
|
|
|
|
public void WriteLine7(string a, string b, string c)
|
|
{
|
|
if (verbose) {
|
|
Console.WriteLine("C: {0}", a + b + c);
|
|
}
|
|
if (a != null) {
|
|
odata += Encoding.ASCII.GetBytes(a, 0, a.Length, obuf, odata);
|
|
}
|
|
if (b != null) {
|
|
odata += Encoding.ASCII.GetBytes(b, 0, b.Length, obuf, odata);
|
|
}
|
|
if (c != null) {
|
|
odata += Encoding.ASCII.GetBytes(c, 0, c.Length, obuf, odata);
|
|
}
|
|
obuf[odata++] = (byte)'\r';
|
|
obuf[odata++] = (byte)'\n';
|
|
socket.Send(obuf, 0, odata, SocketFlags.None);
|
|
odata = 0;
|
|
}
|
|
|
|
public void WriteLine8(byte[] line)
|
|
{
|
|
if (verbose) {
|
|
Console.WriteLine("C: <8bit>");
|
|
}
|
|
if (odata > 0) {
|
|
socket.Send(obuf, 0, odata, SocketFlags.None);
|
|
odata = 0;
|
|
}
|
|
socket.Send(line);
|
|
obuf[odata++] = (byte)'\r';
|
|
obuf[odata++] = (byte)'\n';
|
|
socket.Send(obuf, 0, odata, SocketFlags.None);
|
|
odata = 0;
|
|
}
|
|
|
|
public int Quit()
|
|
{
|
|
int save = result;
|
|
WriteLine7("QUIT");
|
|
ReadLine7();
|
|
socket.Shutdown(SocketShutdown.Both);
|
|
|
|
if (save == 0) {
|
|
return 999;
|
|
}
|
|
return save;
|
|
}
|
|
|
|
public int Close()
|
|
{
|
|
int save = result;
|
|
socket.Shutdown(SocketShutdown.Both);
|
|
|
|
if (save == 0) {
|
|
return 999;
|
|
}
|
|
return save;
|
|
}
|
|
|
|
private void Dump(byte[] array, int beg, int end)
|
|
{
|
|
for (int i = beg; i < end; i += 16) {
|
|
Console.Write(" :: ");
|
|
for (int j = i; j < i + 16; j++) {
|
|
if (j < end) {
|
|
Console.Write("{0:x2}", array[j]);
|
|
}
|
|
else {
|
|
Console.Write(" ");
|
|
}
|
|
}
|
|
Console.Write(" :: ");
|
|
for (int j = i; j < i + 16; j++) {
|
|
if (j < end) {
|
|
if (array[j] >= 32 && array[j] < 127) {
|
|
Console.Write("{0}", (char)array[j]);
|
|
}
|
|
else {
|
|
Console.Write(".");
|
|
}
|
|
}
|
|
else {
|
|
Console.Write(" ");
|
|
}
|
|
}
|
|
Console.WriteLine();
|
|
}
|
|
}
|
|
|
|
public void Dump()
|
|
{
|
|
Console.WriteLine(":::: Input {0}..{1}", ibeg, iend);
|
|
Dump(ibuf, ibeg, iend);
|
|
Console.WriteLine(":::: Output {0}..{1}", 0, odata);
|
|
Dump(obuf, 0, odata);
|
|
Console.WriteLine(":::: Result {0}", result);
|
|
}
|
|
}
|
|
}
|