cc10e0ca351ca36cc2945cab245393abee1f4276
[libt2n] / src / socket_wrapper.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Gerd v. Egidy                                   *
3  *   gve@intra2net.com                                                     *
4  *                                                                         *
5  *   This library is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License version   *
7  *   2.1 as published by the Free Software Foundation.                     *
8  *                                                                         *
9  *   This library is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU Lesser General Public License for more details.                   *
13  *                                                                         *
14  *   You should have received a copy of the GNU Lesser General Public      *
15  *   License along with this program; if not, write to the                 *
16  *   Free Software Foundation, Inc.,                                       *
17  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18  ***************************************************************************/
19
20 #include <functional>
21 #include <string>
22
23 #include <socket_wrapper.hxx>
24
25 namespace libt2n
26 {
27
28 /// return active connection, create new tcp or unix connection if not existing
29 client_connection* BasicSocketWrapper::get_connection(void)
30 {
31     if (c.get() == NULL)
32     {
33         if (socket_type == tcp_s)
34             c=std::auto_ptr<socket_client_connection>
35                 (new socket_client_connection(port,server,connect_timeout_usec,max_retries,logstream,log_level));
36         else if (socket_type == unix_s)
37             c=std::auto_ptr<socket_client_connection>
38                 (new socket_client_connection(path,connect_timeout_usec,max_retries,logstream,log_level));
39     }
40
41     return c.get();
42 }
43
44 /// try to reconnect max_retries time if we encounter a t2n_communication_error 
45 /// during execution of the command
46 bool ReconnectSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
47 {
48     int tries=0;
49
50     while(true)
51     {
52         try
53         {
54             // we always reconnect if something went wrong before:
55             // makes sure the buffers are clean of half-sent packets etc.
56             if (tries > 0)
57                 c->reconnect();
58
59             f();
60             // we were successful
61             return true;
62         }
63         catch(t2n_connect_error &e)
64         {
65             // reconnect already tries max_tries times to reconnect: we are done if that failed
66             throw(e);
67         }
68         catch(t2n_communication_error &e)
69         {
70             // aborts the loop with an exception after max_retries iterations
71             // retries means that the first try doesn't count: use >
72             if (tries > max_retries)
73                 throw(e);
74
75             // otherwise ignore the exception and reconnect in the next iteration
76         }
77         catch(...)
78         {
79             throw;
80         }
81
82         tries++;
83     }
84
85     return false;
86 }
87
88 /// return active connection, return a dummy-connection if we can't establish one
89 client_connection* ReconnectIgnoreFailureSocketWrapper::get_connection(void)
90 {
91     client_connection* tmp=BasicSocketWrapper::get_connection();
92
93     if (tmp->is_closed())
94     {
95         // throw away the closed connection...
96         c.reset();
97         // ...return the dummy one instead
98         tmp=&dc;
99     }
100
101     return tmp;
102 }
103
104 /// try to execute the command, may ignore the command if server not available
105 bool ReconnectIgnoreFailureSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
106 {
107     if (!connection_established())
108     {
109         // dummy connection is in place: try to establish a real one
110         client_connection* tmp=get_connection();
111
112         if (tmp != &dc)
113         {
114             // success! we've got a real connection
115             stubBase->replace_connection(tmp);
116         }
117     }
118
119     // only try to handle the call if we've got a real connection
120     if (connection_established())
121     {
122         try
123         {
124             ReconnectSocketWrapper::handle(stubBase,f);
125             return true;
126         }
127         catch(t2n_communication_error &e)
128         {
129             // ignore
130         }
131         catch(...)
132         {
133             throw;
134         }
135     }
136
137     return false;
138 }
139
140 }