curl-library
LibCurlNet problem reusing easy handle
Date: Mon, 21 May 2012 09:38:37 +0200
Hi,
Thanks for great library!
I'm having some trouble reusing easy handle. What I do.
1) setup connection to use ssl
2) start first transfer it returns ok
3) next transfer returns CURLE_FTP_WRITE_ERROR
Additional info. When I read debug information I find following message:
"522 SSL connection failed; session reuse required: see require_ssl_reuse option
in vsftpd.conf man page
server did not report OK, got 522"
I double checked that my vsftpd has require_ssl_reuse set to YES
I include my code below. What I'm I missing or doing wrong?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SeasideResearch.LibCurlNet;
using System.Threading;
namespace Exnui
{
static class Global
{
public static void Init()
{
Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
}
public static void CleanUp()
{
Curl.GlobalCleanup();
}
}
public enum OpStatus
{
Waiting,
Cancelled,
Success,
Error
}
static class FtpsManager
{
private static Queue<FtpsOp> ops;
private static Easy conn;
private static bool cancelCurrentOpValue;
private static bool runningValue;
private static readonly object cancelSyncRoot = new object();
private static readonly object stopSyncRoot = new object();
private static readonly object runningSyncRoot = new object();
static FtpsManager()
{
ops = new Queue<FtpsOp>(200); // initial size 200
conn = new Easy();
cancelCurrentOpValue = false;
runningValue = false;
// setup credential
conn.SetOpt(CURLoption.CURLOPT_USERPWD, Config.FtpsLogin +
":" + Config.FtpsPassword);
// short dir list, names only
conn.SetOpt(CURLoption.CURLOPT_FTPLISTONLY, true);
// enable ssl
conn.SetOpt(CURLoption.CURLOPT_FTP_SSL, CURLftpSSL.CURLFTPSSL_TRY);
// fuck server certificate
conn.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, false);
conn.SetOpt(CURLoption.CURLOPT_SSL_VERIFYHOST, 1); // 1
means - check cert existence, screw content
// make curl more talkative
conn.SetOpt(CURLoption.CURLOPT_VERBOSE, true);
// enable progress callback
conn.SetOpt(CURLoption.CURLOPT_NOPROGRESS, 0);
Easy.ProgressFunction delegProgress = new
Easy.ProgressFunction(Progress);
conn.SetOpt(CURLoption.CURLOPT_PROGRESSFUNCTION, delegProgress);
// debug
Easy.DebugFunction delegDebug = new Easy.DebugFunction(Debug);
conn.SetOpt(CURLoption.CURLOPT_DEBUGFUNCTION, delegDebug);
conn.SetOpt(CURLoption.CURLOPT_VERBOSE, true);
// test
// conn.SetOpt(CURLoption.CURLOPT_SSL_SESSIONID_CACHE,
}
public static void Entry()
{
while (Running)
{
try
{
FtpsOp currentOp;
object opsSyncRoot = (ops as ICollection).SyncRoot;
lock (opsSyncRoot)
{
if (ops.Count == 0)
{
Monitor.Wait(opsSyncRoot);
}
currentOp = ops.First();
}
bool res = currentOp.Execute(conn);
if (CancelCurrent)
{
Console.WriteLine("Manager cancelled op");
CancelCurrent = false;
}
if (res)
{
// remove op from queue
lock (opsSyncRoot)
{
ops.Dequeue();
}
}
else
{
// for now just act like everything was allright
lock (opsSyncRoot)
{
ops.Dequeue();
}
// todo
// retry x time
// check internet connection
// - some .net connection state
// - ping always on servies google, etc.
}
}
catch (ThreadAbortException abort)
{
// nasty error - tis shouldn't happen
Running = false;
CancelCurrent = true;
Log.Error("FtpsManager thread aborted");
Log.Exception(abort);
// todo
// dump queue to file or restore it from
"commands" database
// "commands" database are json structs I get from exnui
}
catch (ThreadInterruptedException)
{
// nasty but we eat this exception
}
finally
{
// clean up
}
}
}
public static void Start()
{
// Only one thread can work on Ops Queue
if (Running == false)
{
Running = true;
Thread managerThread = new Thread(new ThreadStart(Entry));
managerThread.Start();
}
}
// Cancels current op
public static void Cancel()
{
CancelCurrent = true;
}
public static void Stop()
{
Running = false;
}
private static bool Running
{
get
{
lock (runningSyncRoot)
{
return runningValue;
}
}
set
{
lock (runningSyncRoot)
{
runningValue = value;
}
}
}
public static bool CancelCurrent
{
get
{
lock (cancelSyncRoot)
{
return cancelCurrentOpValue;
}
}
set
{
lock (cancelSyncRoot)
{
cancelCurrentOpValue = value;
}
}
}
public static void EnqueOp(FtpsOp op)
{
Object syncRoot = (ops as ICollection).SyncRoot;
lock (syncRoot)
{
if (op != null)
{
ops.Enqueue(op);
}
Monitor.Pulse(syncRoot);
}
}
public static void Debug(CURLINFOTYPE infoType, String msg,
Object userData)
{
//Console.WriteLine(msg);
}
public static Int32 Progress(Object extraData, Double dlTotal,
Double dlNow, Double ulTotal, Double ulNow)
{
// 0 - ok
// 1 - abort
Console.WriteLine("Progress");
int res = CancelCurrent ? 1 : 0;
return res;
}
public static void Close()
{
conn.Cleanup();
}
}
abstract class FtpsOp
{
protected string localPath;
protected string remotePath;
protected OpStatus opStatus;
public FtpsOp(string localPath, string remotePath)
{
this.localPath = localPath;
this.remotePath = remotePath;
this.opStatus = OpStatus.Waiting;
}
public abstract bool Execute(Easy conn);
}
class FtpsUploadFile : FtpsOp
{
static int elapsedTime = 0;
static int totalWritten = 0;
public FtpsUploadFile(string localPath, string remotePath)
: base(localPath, remotePath)
{
}
public override bool Execute(Easy conn)
{
FileStream ifs = null;
try
{
// Debug
Console.WriteLine("Uploading file: {0}", localPath);
ifs = File.OpenRead(localPath);
// setup url
string url = Config.FtpsUrl + remotePath.Replace(@"\", @"/");
conn.SetOpt(CURLoption.CURLOPT_URL, url);
// setup upload info
conn.SetOpt(CURLoption.CURLOPT_UPLOAD, true);
conn.SetOpt(CURLoption.CURLOPT_INFILESIZE_LARGE, ifs.Length);
// setup delegate for reading binary data
Easy.ReadFunction delegReadBinary = new
Easy.ReadFunction(ReadBinary);
conn.SetOpt(CURLoption.CURLOPT_READFUNCTION, delegReadBinary);
conn.SetOpt(CURLoption.CURLOPT_READDATA, ifs);
// do transfer
CURLcode curlStatus = conn.Perform();
bool succ = false;
if (curlStatus == CURLcode.CURLE_OK)
{
succ = true;
opStatus = OpStatus.Success;
}
// Debug
Console.WriteLine("CurlStatus: {0} OpStatus: {1}",
curlStatus, opStatus);
return succ;
}
catch (Exception e)
{
Log.Exception(e);
throw;
}
finally
{
if (ifs != null)
{
ifs.Close();
//conn.SetOpt(CURLoption.CURLOPT_UPLOAD, false);
//conn.SetOpt(CURLoption.CURLOPT_INFILESIZE_LARGE, 0L);
}
}
}
private Int32 ReadBinary(Byte[] buf, Int32 size, Int32 count,
Object userData)
{
// Debug
//Console.WriteLine("Size: {0} Count: {1}", size, count);
/*
if (FtpsManager.CancelCurrent)
{
opStatus = OpStatus.Cancelled;
// Debug
Console.WriteLine("Transfer cancelled");
// Return value CURL_READFUNC_ABORT abort transfer -
libcurl doc, don't return 0
// Curl.net you should return 0 to abort
return 0;
}
*/
FileStream fs = (FileStream)userData;
int total = size * count;
// Debug
// Console.WriteLine("Just before stream.Read");
int res = 0;
try
{
res = fs.Read(buf, 0, total);
}
catch(Exception)
{
Console.WriteLine("Exception in ReadBinary");
}
return res;
}
}
}
/*
*
* MAIN
*
*/
using System;
using System.Collections;
using System.Threading;
namespace Exnui
{
class App
{
static void Main(string[] args)
{
Global.Init();
string[] files =
{
@"\prayer.mp3",
@"\tekst.txt",
@"\tekst.txt"
};
FtpsManager.Start();
foreach (var file in files)
{
FtpsUploadFile op = new
FtpsUploadFile(Config.CachePath + file, file);
FtpsManager.EnqueOp(op);
}
int second = 1000;
int minute = 60000;
Thread.Sleep(200 * minute);
FtpsManager.Stop();
Global.CleanUp();
}
}
}
Any help would be welcomed!
Best regards,
Lukasz
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2012-05-21