├── .gitignore
├── AsyncIpc.sln
├── README.md
├── ipc
├── ReadMe.txt
├── ipc.vcxproj
├── ipc.vcxproj.filters
├── ipc_channel.cpp
├── ipc_channel.h
├── ipc_channel_handle.h
├── ipc_channel_reader.cpp
├── ipc_channel_reader.h
├── ipc_common.h
├── ipc_endpoint.cpp
├── ipc_endpoint.h
├── ipc_interface.h
├── ipc_listener.h
├── ipc_logging.cc
├── ipc_logging.h
├── ipc_message.cpp
├── ipc_message.h
├── ipc_sender.h
├── ipc_thread.cpp
├── ipc_thread.h
├── ipc_utils.cpp
├── ipc_utils.h
├── stdafx.cpp
└── stdafx.h
├── ipc_dll
├── ReadMe.txt
├── ipc_dll.cpp
├── ipc_dll.def
├── ipc_dll.h
├── ipc_dll.vcxproj
├── ipc_dll.vcxproj.filters
├── ipc_endpoint_impl.cpp
├── ipc_endpoint_impl.h
├── ipc_factory_impl.cpp
├── ipc_factory_impl.h
├── stdafx.cpp
├── stdafx.h
└── targetver.h
└── sample
├── ReadMe.txt
├── common.cpp
├── common.h
├── sample_client.cpp
├── sample_client.h
├── sample_client.vcxproj
├── sample_client.vcxproj.filters
├── sample_dll_client.cpp
├── sample_dll_client.h
├── sample_dll_client.vcxproj
├── sample_dll_client.vcxproj.filters
├── stdafx.cpp
├── stdafx.h
└── targetver.h
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Visual Studio
3 | #################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.sln.docstates
12 |
13 | # Build results
14 | #[Dd]ebug/
15 | #[Rr]elease/
16 | *_i.c
17 | *_p.c
18 | *.ilk
19 | *.meta
20 | *.obj
21 | *.pch
22 | *.pdb
23 | *.pgc
24 | *.pgd
25 | *.rsp
26 | *.sbr
27 | *.tlb
28 | *.tli
29 | *.tlh
30 | *.tmp
31 | *.vspscc
32 | .builds
33 | *.dotCover
34 |
35 | # Visual C++ cache files
36 | ipch/
37 | *.aps
38 | *.ncb
39 | *.opensdf
40 | *.sdf
41 |
42 | # Visual Studio profiler
43 | *.psess
44 | *.vsp
45 |
46 | #################
47 | /build/
48 | /output/
49 | /ipch/
--------------------------------------------------------------------------------
/AsyncIpc.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30501.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipc", "ipc\ipc.vcxproj", "{896C53B4-9517-429A-911C-1A2B634B8319}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_client", "sample\sample_client.vcxproj", "{ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipc_dll", "ipc_dll\ipc_dll.vcxproj", "{A808021A-C2FF-4B8D-A24A-B3535BCA0637}"
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_dll_client", "sample\sample_dll_client.vcxproj", "{F15D047E-1369-432E-91C0-03E932370D55}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Win32 = Debug|Win32
17 | Release|Win32 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {896C53B4-9517-429A-911C-1A2B634B8319}.Debug|Win32.ActiveCfg = Debug|Win32
21 | {896C53B4-9517-429A-911C-1A2B634B8319}.Debug|Win32.Build.0 = Debug|Win32
22 | {896C53B4-9517-429A-911C-1A2B634B8319}.Release|Win32.ActiveCfg = Release|Win32
23 | {896C53B4-9517-429A-911C-1A2B634B8319}.Release|Win32.Build.0 = Release|Win32
24 | {ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}.Debug|Win32.ActiveCfg = Debug|Win32
25 | {ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}.Debug|Win32.Build.0 = Debug|Win32
26 | {ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}.Release|Win32.ActiveCfg = Release|Win32
27 | {ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}.Release|Win32.Build.0 = Release|Win32
28 | {A808021A-C2FF-4B8D-A24A-B3535BCA0637}.Debug|Win32.ActiveCfg = Debug|Win32
29 | {A808021A-C2FF-4B8D-A24A-B3535BCA0637}.Debug|Win32.Build.0 = Debug|Win32
30 | {A808021A-C2FF-4B8D-A24A-B3535BCA0637}.Release|Win32.ActiveCfg = Release|Win32
31 | {A808021A-C2FF-4B8D-A24A-B3535BCA0637}.Release|Win32.Build.0 = Release|Win32
32 | {F15D047E-1369-432E-91C0-03E932370D55}.Debug|Win32.ActiveCfg = Debug|Win32
33 | {F15D047E-1369-432E-91C0-03E932370D55}.Debug|Win32.Build.0 = Debug|Win32
34 | {F15D047E-1369-432E-91C0-03E932370D55}.Release|Win32.ActiveCfg = Release|Win32
35 | {F15D047E-1369-432E-91C0-03E932370D55}.Release|Win32.Build.0 = Release|Win32
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #AsyncIpc
2 | ========
3 |
4 | * 异步进程间通信库
5 | * 提供静态库和动态dll加载方式
6 | * 轻量,动态dll只有40K
7 |
--------------------------------------------------------------------------------
/ipc/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | STATIC LIBRARY : ipc Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this ipc library project for you.
6 |
7 | No source files were created as part of your project.
8 |
9 |
10 | ipc.vcxproj
11 | This is the main project file for VC++ projects generated using an Application Wizard.
12 | It contains information about the version of Visual C++ that generated the file, and
13 | information about the platforms, configurations, and project features selected with the
14 | Application Wizard.
15 |
16 | ipc.vcxproj.filters
17 | This is the filters file for VC++ projects generated using an Application Wizard.
18 | It contains information about the association between the files in your project
19 | and the filters. This association is used in the IDE to show grouping of files with
20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
21 | "Source Files" filter).
22 |
23 | /////////////////////////////////////////////////////////////////////////////
24 | Other notes:
25 |
26 | AppWizard uses "TODO:" comments to indicate parts of the source code you
27 | should add to or customize.
28 |
29 | /////////////////////////////////////////////////////////////////////////////
30 |
--------------------------------------------------------------------------------
/ipc/ipc.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {896C53B4-9517-429A-911C-1A2B634B8319}
15 | Win32Proj
16 | ipc
17 |
18 |
19 |
20 | StaticLibrary
21 | true
22 | v120_xp
23 | Unicode
24 |
25 |
26 | StaticLibrary
27 | false
28 | v120_xp
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ..\output\$(Configuration)\
44 | ..\build\$(ProjectName)\$(Configuration)\
45 |
46 |
47 | ..\output\$(Configuration)\
48 | ..\build\$(ProjectName)\$(Configuration)\
49 |
50 |
51 |
52 |
53 |
54 | Level3
55 | Disabled
56 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
57 | true
58 | $(projectdir)..;%(AdditionalIncludeDirectories)
59 | stdafx.h
60 |
61 |
62 | Windows
63 | true
64 |
65 |
66 |
67 |
68 | Level3
69 |
70 |
71 | MaxSpeed
72 | true
73 | true
74 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
75 | true
76 | $(projectdir)..;%(AdditionalIncludeDirectories)
77 | stdafx.h
78 |
79 |
80 | Windows
81 | true
82 | true
83 | true
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/ipc/ipc.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {e70582e1-e6af-4bde-9881-706dd6704a4f}
6 |
7 |
8 | {1535d84c-3a6e-47e7-ac29-be88e042a049}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | ipc
17 |
18 |
19 | ipc
20 |
21 |
22 | ipc
23 |
24 |
25 | ipc
26 |
27 |
28 | ipc
29 |
30 |
31 | ipc
32 |
33 |
34 | ipc
35 |
36 |
37 | ipc
38 |
39 |
40 | build
41 |
42 |
43 | ipc
44 |
45 |
46 | ipc
47 |
48 |
49 |
50 |
51 | ipc
52 |
53 |
54 | ipc
55 |
56 |
57 | ipc
58 |
59 |
60 | ipc
61 |
62 |
63 | build
64 |
65 |
66 | ipc
67 |
68 |
69 | ipc
70 |
71 |
72 |
--------------------------------------------------------------------------------
/ipc/ipc_channel.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hicdre/AsyncIpc/8253b2bad7a6f17f972294827ae13df47292f047/ipc/ipc_channel.cpp
--------------------------------------------------------------------------------
/ipc/ipc_channel.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_CHANNEL_WIN_H_
6 | #define IPC_IPC_CHANNEL_WIN_H_
7 |
8 | #include
9 | #include
10 |
11 | #include "ipc/ipc_common.h"
12 | #include "ipc/ipc_thread.h"
13 | #include "ipc/ipc_sender.h"
14 | #include "ipc/ipc_channel_handle.h"
15 | #include "ipc/ipc_channel_reader.h"
16 |
17 | namespace IPC
18 | {
19 | class Channel
20 | : public Sender
21 | , public internal::ChannelReader
22 | , public Thread::IOHandler
23 | {
24 | public:
25 | enum {
26 | HELLO_MESSAGE_TYPE = kuint16max // Maximum value of message type (uint16),
27 | // to avoid conflicting with normal
28 | // message types, which are enumeration
29 | // constants starting from 0.
30 | };
31 |
32 | // The maximum message size in bytes. Attempting to receive a message of this
33 | // size or bigger results in a channel error.
34 | static const size_t kMaximumMessageSize = 128 * 1024 * 1024;
35 |
36 | // Mirror methods of Channel, see ipc_channel.h for description.
37 | Channel(const IPC::ChannelHandle &channel_handle,
38 | Listener* listener, Thread* thread);
39 | ~Channel();
40 | bool Connect();
41 | void Close();
42 | virtual bool Send(Message* message) override;
43 | DWORD peer_pid() const { return peer_pid_; }
44 |
45 | private:
46 | // Returns true if a named server channel is initialized on the given channel
47 | // ID. Even if true, the server may have already accepted a connection.
48 | static bool IsNamedServerInitialized(const std::string& channel_id);
49 |
50 | // Generates a channel ID that's non-predictable and unique.
51 | static std::string GenerateUniqueRandomChannelID();
52 |
53 | // Generates a channel ID that, if passed to the client as a shared secret,
54 | // will validate that the client's authenticity. On platforms that do not
55 | // require additional this is simply calls GenerateUniqueRandomChannelID().
56 | // For portability the prefix should not include the \ character.
57 | static std::string GenerateVerifiedChannelID(const std::string& prefix);
58 | private:
59 | // ChannelReader implementation.
60 | virtual ReadState ReadData(char* buffer,
61 | int buffer_len,
62 | int* bytes_read) override;
63 | virtual bool WillDispatchInputMessage(Message* msg) override;
64 | bool DidEmptyInputBuffers() override;
65 | virtual void HandleHelloMessage(Message* msg) override;
66 |
67 | static const std::wstring PipeName(const std::string& channel_id,
68 | int32* secret);
69 | bool CreatePipe(const IPC::ChannelHandle &channel_handle);
70 |
71 | bool ProcessConnection();
72 | bool ProcessOutgoingMessages(Thread::IOContext* context,
73 | DWORD bytes_written);
74 |
75 | // MessageLoop::IOHandler implementation.
76 | virtual void OnIOCompleted(Thread::IOContext* context,
77 | DWORD bytes_transfered,
78 | DWORD error);
79 |
80 | private:
81 | struct State {
82 | explicit State(Channel* channel);
83 | ~State();
84 | Thread::IOContext context;
85 | bool is_pending;
86 | };
87 |
88 | State input_state_;
89 | State output_state_;
90 |
91 | HANDLE pipe_;
92 |
93 | DWORD peer_pid_;
94 |
95 | // Messages to be sent are queued here.
96 | std::queue output_queue_;
97 |
98 | // In server-mode, we have to wait for the client to connect before we
99 | // can begin reading. We make use of the input_state_ when performing
100 | // the connect operation in overlapped mode.
101 | bool waiting_connect_;
102 |
103 | // This flag is set when processing incoming messages. It is used to
104 | // avoid recursing through ProcessIncomingMessages, which could cause
105 | // problems. TODO(darin): make this unnecessary
106 | bool processing_incoming_;
107 |
108 | // Determines if we should validate a client's secret on connection.
109 | bool validate_client_;
110 |
111 | // This is a unique per-channel value used to authenticate the client end of
112 | // a connection. If the value is non-zero, the client passes it in the hello
113 | // and the host validates. (We don't send the zero value fto preserve IPC
114 | // compatability with existing clients that don't validate the channel.)
115 | int32 client_secret_;
116 |
117 | Thread* thread_;
118 |
119 | DISALLOW_COPY_AND_ASSIGN(Channel);
120 | };
121 |
122 | } // namespace IPC
123 |
124 | #endif // IPC_IPC_CHANNEL_WIN_H_
125 |
--------------------------------------------------------------------------------
/ipc/ipc_channel_handle.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_CHANNEL_HANDLE_H_
6 | #define IPC_IPC_CHANNEL_HANDLE_H_
7 |
8 | #include
9 | #include
10 |
11 | // On Windows, any process can create an IPC channel and others can fetch
12 | // it by name. We pass around the channel names over IPC.
13 | // On Windows the initialization of ChannelHandle with an existing pipe
14 | // handle is provided for convenience.
15 | // NOTE: A ChannelHandle with a pipe handle Will NOT be marshalled over IPC.
16 |
17 | // On POSIX, we instead pass around handles to channel endpoints via IPC.
18 | // When it's time to IPC a new channel endpoint around, we send both the
19 | // channel name as well as a base::FileDescriptor, which is itself a special
20 | // type that knows how to copy a socket endpoint over IPC.
21 | //
22 | // In sum, this data structure can be used to pass channel information by name
23 | // in both Windows and Posix. When passing a handle to a channel over IPC,
24 | // use this data structure only for POSIX.
25 |
26 | namespace IPC {
27 |
28 | struct ChannelHandle {
29 | // Note that serialization for this object is defined in the ParamTraits
30 | // template specialization in ipc_message_utils.h.
31 | ChannelHandle() {}
32 | // The name that is passed in should be an absolute path for Posix.
33 | // Otherwise there may be a problem in IPC communication between
34 | // processes with different working directories.
35 | ChannelHandle(const std::string& n) : name(n) {}
36 | ChannelHandle(const char* n) : name(n) {}
37 | explicit ChannelHandle(HANDLE h) : pipe(h) {}
38 |
39 | std::string name;
40 | // A simple container to automatically initialize pipe handle
41 | struct PipeHandle {
42 | PipeHandle() : handle(NULL) {}
43 | PipeHandle(HANDLE h) : handle(h) {}
44 | HANDLE handle;
45 | };
46 | PipeHandle pipe;
47 | };
48 |
49 | } // namespace IPC
50 |
51 | #endif // IPC_IPC_CHANNEL_HANDLE_H_
52 |
--------------------------------------------------------------------------------
/ipc/ipc_channel_reader.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "ipc/ipc_channel_reader.h"
6 |
7 | #include "ipc/ipc_listener.h"
8 | #include "ipc/ipc_message.h"
9 | #include "ipc/ipc_channel.h"
10 | //#include "ipc/ipc_logging.h"
11 | #include
12 |
13 | namespace IPC {
14 | namespace internal {
15 |
16 | ChannelReader::ChannelReader(Listener* listener) : listener_(listener) {
17 | memset(input_buf_, 0, sizeof(input_buf_));
18 | }
19 |
20 | ChannelReader::~ChannelReader() {
21 | }
22 |
23 | bool ChannelReader::ProcessIncomingMessages() {
24 | while (true) {
25 | int bytes_read = 0;
26 | ReadState read_state = ReadData(input_buf_, kReadBufferSize,
27 | &bytes_read);
28 | if (read_state == READ_FAILED)
29 | return false;
30 | if (read_state == READ_PENDING)
31 | return true;
32 |
33 | assert(bytes_read > 0);
34 | if (!DispatchInputData(input_buf_, bytes_read))
35 | return false;
36 | }
37 | }
38 |
39 | bool ChannelReader::AsyncReadComplete(int bytes_read) {
40 | return DispatchInputData(input_buf_, bytes_read);
41 | }
42 |
43 | bool ChannelReader::IsHelloMessage(Message* m) const {
44 | return m->routing_id() == MSG_ROUTING_NONE &&
45 | m->type() == Channel::HELLO_MESSAGE_TYPE;
46 | }
47 |
48 | bool ChannelReader::DispatchInputData(const char* input_data,
49 | int input_data_len) {
50 | const char* p;
51 | const char* end;
52 |
53 | // Possibly combine with the overflow buffer to make a larger buffer.
54 | if (input_overflow_buf_.empty()) {
55 | p = input_data;
56 | end = input_data + input_data_len;
57 | } else {
58 | if (input_overflow_buf_.size() + input_data_len >
59 | Channel::kMaximumMessageSize) {
60 | input_overflow_buf_.clear();
61 | //assert(ERROR) << "IPC message is too big";
62 | return false;
63 | }
64 | input_overflow_buf_.append(input_data, input_data_len);
65 | p = input_overflow_buf_.data();
66 | end = p + input_overflow_buf_.size();
67 | }
68 |
69 | // Dispatch all complete messages in the data buffer.
70 | while (p < end) {
71 | const char* message_tail = Message::FindNext(p, end);
72 | if (message_tail) {
73 | int len = static_cast(message_tail - p);
74 | Message* m = new Message(p, len);
75 | m->AddRef();
76 | if (!WillDispatchInputMessage(m))
77 | return false;
78 |
79 | #ifdef IPC_MESSAGE_LOG_ENABLED
80 | Logging* logger = Logging::GetInstance();
81 | std::string name;
82 | logger->GetMessageText(m.type(), &name, &m, NULL);
83 | TRACE_EVENT1("ipc", "ChannelReader::DispatchInputData", "name", name);
84 | #else
85 | //TRACE_EVENT2("ipc", "ChannelReader::DispatchInputData",
86 | // "class", IPC_MESSAGE_ID_CLASS(m.type()),
87 | // "line", IPC_MESSAGE_ID_LINE(m.type()));
88 | #endif
89 | //m.TraceMessageEnd();
90 | if (IsHelloMessage(m))
91 | HandleHelloMessage(m);
92 | else
93 | listener_->OnMessageReceived(m);
94 | p = message_tail;
95 | } else {
96 | // Last message is partial.
97 | break;
98 | }
99 | }
100 |
101 | // Save any partial data in the overflow buffer.
102 | input_overflow_buf_.assign(p, end - p);
103 |
104 | if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
105 | return false;
106 | return true;
107 | }
108 |
109 |
110 | } // namespace internal
111 | } // namespace IPC
112 |
--------------------------------------------------------------------------------
/ipc/ipc_channel_reader.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_CHANNEL_READER_H_
6 | #define IPC_IPC_CHANNEL_READER_H_
7 |
8 | #include "ipc/ipc_listener.h"
9 | #include "ipc/ipc_common.h"
10 |
11 | namespace IPC {
12 | namespace internal {
13 |
14 | // This class provides common pipe reading functionality for the
15 | // platform-specific IPC channel implementations.
16 | //
17 | // It does the common input buffer management and message dispatch, while the
18 | // platform-specific parts provide the pipe management through a virtual
19 | // interface implemented on a per-platform basis.
20 | //
21 | // Note that there is no "writer" corresponding to this because the code for
22 | // writing to the channel is much simpler and has very little common
23 | // functionality that would benefit from being factored out. If we add
24 | // something like that in the future, it would be more appropriate to add it
25 | // here (and rename appropriately) rather than writing a different class.
26 | class ChannelReader {
27 | public:
28 | // Amount of data to read at once from the pipe.
29 | static const size_t kReadBufferSize = 4 * 1024;
30 |
31 | explicit ChannelReader(Listener* listener);
32 | virtual ~ChannelReader();
33 |
34 | void set_listener(Listener* listener) { listener_ = listener; }
35 |
36 | // Call to process messages received from the IPC connection and dispatch
37 | // them. Returns false on channel error. True indicates that everything
38 | // succeeded, although there may not have been any messages processed.
39 | bool ProcessIncomingMessages();
40 |
41 | // Handles asynchronously read data.
42 | //
43 | // Optionally call this after returning READ_PENDING from ReadData to
44 | // indicate that buffer was filled with the given number of bytes of
45 | // data. See ReadData for more.
46 | bool AsyncReadComplete(int bytes_read);
47 |
48 | // Returns true if the given message is the "hello" message sent on channel
49 | // set-up.
50 | bool IsHelloMessage(Message* m) const;
51 |
52 | protected:
53 | enum ReadState { READ_SUCCEEDED, READ_FAILED, READ_PENDING };
54 |
55 | Listener* listener() const { return listener_; }
56 |
57 | // Populates the given buffer with data from the pipe.
58 | //
59 | // Returns the state of the read. On READ_SUCCESS, the number of bytes
60 | // read will be placed into |*bytes_read| (which can be less than the
61 | // buffer size). On READ_FAILED, the channel will be closed.
62 | //
63 | // If the return value is READ_PENDING, it means that there was no data
64 | // ready for reading. The implementation is then responsible for either
65 | // calling AsyncReadComplete with the number of bytes read into the
66 | // buffer, or ProcessIncomingMessages to try the read again (depending
67 | // on whether the platform's async I/O is "try again" or "write
68 | // asynchronously into your buffer").
69 | virtual ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) = 0;
70 |
71 | // Loads the required file desciptors into the given message. Returns true
72 | // on success. False means a fatal channel error.
73 | //
74 | // This will read from the input_fds_ and read more handles from the FD
75 | // pipe if necessary.
76 | virtual bool WillDispatchInputMessage(Message* msg) = 0;
77 |
78 | // Performs post-dispatch checks. Called when all input buffers are empty,
79 | // though there could be more data ready to be read from the OS.
80 | virtual bool DidEmptyInputBuffers() = 0;
81 |
82 | // Handles the first message sent over the pipe which contains setup info.
83 | virtual void HandleHelloMessage(Message* msg) = 0;
84 |
85 | private:
86 | // Takes the given data received from the IPC channel and dispatches any
87 | // fully completed messages.
88 | //
89 | // Returns true on success. False means channel error.
90 | bool DispatchInputData(const char* input_data, int input_data_len);
91 |
92 | Listener* listener_;
93 |
94 | // We read from the pipe into this buffer. Managed by DispatchInputData, do
95 | // not access directly outside that function.
96 | char input_buf_[kReadBufferSize];
97 |
98 | // Large messages that span multiple pipe buffers, get built-up using
99 | // this buffer.
100 | std::string input_overflow_buf_;
101 |
102 | DISALLOW_COPY_AND_ASSIGN(ChannelReader);
103 | };
104 |
105 | } // namespace internal
106 | } // namespace IPC
107 |
108 | #endif // IPC_IPC_CHANNEL_READER_H_
109 |
--------------------------------------------------------------------------------
/ipc/ipc_common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | typedef signed char schar;
6 | typedef signed char int8;
7 | typedef short int16;
8 | typedef int int32;
9 |
10 | typedef long long int64;
11 |
12 | typedef unsigned char uint8;
13 | typedef unsigned short uint16;
14 | typedef unsigned int uint32;
15 |
16 | typedef unsigned long long uint64;
17 |
18 | const uint16 kuint16max = ((uint16)0xFFFF);
19 | const int32 kint32max = ((int32)0x7FFFFFFF);
20 |
21 | // A macro to disallow the copy constructor and operator= functions
22 | // This should be used in the private: declarations for a class
23 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
24 | TypeName(const TypeName&); \
25 | void operator=(const TypeName&)
26 |
--------------------------------------------------------------------------------
/ipc/ipc_endpoint.cpp:
--------------------------------------------------------------------------------
1 | #include "ipc_endpoint.h"
2 | #include "ipc/ipc_message.h"
3 | #include
4 |
5 | namespace IPC
6 | {
7 |
8 | Endpoint::Endpoint(const std::string& name, Listener* listener, bool start_now)
9 | : name_(name)
10 | , listener_(listener)
11 | , is_connected_(false)
12 | {
13 | thread_.Start();
14 | if (start_now)
15 | Start();
16 | }
17 |
18 | Endpoint::~Endpoint()
19 | {
20 | SetConnected(false);
21 | if (channel_)
22 | {
23 | HANDLE wait_event = ::CreateEvent(NULL, FALSE, FALSE, NULL);
24 | thread_.PostTask(std::bind(&Endpoint::CloseChannel, this, wait_event));
25 | DWORD ret = ::WaitForSingleObject(wait_event, 2000);
26 | assert(ret == WAIT_OBJECT_0);
27 | CloseHandle(wait_event);
28 | delete channel_;
29 | channel_ = NULL;
30 | }
31 | thread_.Stop();
32 | thread_.Wait(2000);
33 | }
34 |
35 | void Endpoint::Start()
36 | {
37 | if (channel_ == NULL)
38 | thread_.PostTask(std::bind(&Endpoint::CreateChannel, this));
39 | }
40 |
41 |
42 | bool Endpoint::IsConnected() const
43 | {
44 | AutoLock lock(lock_);
45 | return is_connected_;
46 | }
47 |
48 |
49 | void Endpoint::SetConnected(bool c)
50 | {
51 | AutoLock lock(lock_);
52 | is_connected_ = c;
53 | }
54 |
55 |
56 | void Endpoint::CreateChannel()
57 | {
58 | if (channel_)
59 | return;
60 |
61 | channel_ = new Channel(name_, this, &thread_);
62 | channel_->Connect();
63 | }
64 |
65 | bool Endpoint::Send(Message* message)
66 | {
67 | scoped_refptr m(message);
68 | if (channel_ == NULL || !IsConnected()) {
69 | return false;
70 | }
71 | thread_.PostTask(std::bind(&Endpoint::OnSendMessage, this, m));
72 | return true;
73 | }
74 |
75 |
76 | void Endpoint::OnSendMessage(scoped_refptr message)
77 | {
78 | if (channel_ == NULL)
79 | return;
80 |
81 | channel_->Send(message.get());
82 | }
83 |
84 |
85 | bool Endpoint::OnMessageReceived(Message* message)
86 | {
87 | return listener_->OnMessageReceived(message);
88 | }
89 |
90 | void Endpoint::OnChannelConnected(int32 peer_pid)
91 | {
92 | SetConnected(true);
93 | listener_->OnChannelConnected(peer_pid);
94 | }
95 |
96 | void Endpoint::OnChannelError()
97 | {
98 | Channel* ch = channel_;
99 | channel_ = NULL;
100 | delete ch;
101 | SetConnected(false);
102 | listener_->OnChannelError();
103 | Start();
104 | }
105 |
106 | void Endpoint::CloseChannel(HANDLE wait_event)
107 | {
108 | Channel* ch = channel_;
109 | channel_ = NULL;
110 | delete ch;
111 | SetEvent(wait_event);
112 | }
113 |
114 |
115 | }
--------------------------------------------------------------------------------
/ipc/ipc_endpoint.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ipc/ipc_thread.h"
3 | #include "ipc/ipc_channel.h"
4 | #include "ipc/ipc_listener.h"
5 |
6 | namespace IPC
7 | {
8 | class Endpoint : public Sender, public Listener
9 | {
10 | public:
11 | Endpoint(const std::string& name, Listener* listener, bool start_now = true);
12 | ~Endpoint();
13 |
14 | void Start();
15 |
16 | bool IsConnected() const;
17 |
18 | virtual bool Send(Message* message) override;
19 |
20 | virtual bool OnMessageReceived(Message* message) override;
21 |
22 | virtual void OnChannelConnected(int32 peer_pid) override;
23 |
24 | virtual void OnChannelError() override;
25 |
26 | private:
27 | void CreateChannel();
28 | void OnSendMessage(scoped_refptr message);
29 | void CloseChannel(HANDLE wait_event);
30 | void SetConnected(bool c);
31 | std::string name_;
32 | Thread thread_;
33 |
34 | Channel* channel_;
35 | Listener* listener_;
36 | //std::queue
37 |
38 | mutable Lock lock_;
39 | bool is_connected_;
40 | };
41 | }
--------------------------------------------------------------------------------
/ipc/ipc_interface.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace IPC
4 | {
5 | enum ErrorCode
6 | {
7 | ERROR_OK = 0,
8 |
9 | ERROR_MESSAGE_READONLY = 1,
10 |
11 | ERROR_DEST_DISCONNECTED = 2,
12 | };
13 |
14 | class IListener
15 | {
16 | public:
17 | virtual void AddRef() const = 0;
18 | virtual void Release() const = 0;
19 | virtual void OnMessageReceived(const char* message, size_t len) {};
20 | virtual void OnDestConnected(int process_id) {}
21 | virtual void OnDestDisconnected() {}
22 | };
23 |
24 | class IEndpoint
25 | {
26 | public:
27 | virtual void AddRef() const = 0;
28 | virtual void Release() const = 0;
29 | virtual ErrorCode Send(const char* message, size_t len) = 0;
30 | virtual bool HasListener() const = 0;
31 | virtual void SetListener(IListener* listener) = 0;
32 | };
33 |
34 | }
--------------------------------------------------------------------------------
/ipc/ipc_listener.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_LISTENER_H_
6 | #define IPC_IPC_LISTENER_H_
7 |
8 | #include "ipc/ipc_common.h"
9 |
10 | namespace IPC {
11 |
12 | class Message;
13 |
14 | // Implemented by consumers of a Channel to receive messages.
15 | class Listener {
16 | public:
17 | // Called when a message is received. Returns true iff the message was
18 | // handled.
19 | virtual bool OnMessageReceived(Message* message) = 0;
20 |
21 | // Called when the channel is connected and we have received the internal
22 | // Hello message from the peer.
23 | virtual void OnChannelConnected(int32 peer_pid) {}
24 |
25 | // Called when an error is detected that causes the channel to close.
26 | // This method is not called when a channel is closed normally.
27 | virtual void OnChannelError() {}
28 |
29 | protected:
30 | virtual ~Listener() {}
31 | };
32 |
33 | } // namespace IPC
34 |
35 | #endif // IPC_IPC_LISTENER_H_
36 |
--------------------------------------------------------------------------------
/ipc/ipc_logging.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "ipc/ipc_logging.h"
6 |
7 | #ifdef IPC_MESSAGE_LOG_ENABLED
8 | #define IPC_MESSAGE_MACROS_LOG_ENABLED
9 | #endif
10 |
11 | #include "base/bind.h"
12 | #include "base/bind_helpers.h"
13 | #include "base/command_line.h"
14 | #include "base/location.h"
15 | #include "base/logging.h"
16 | #include "base/message_loop.h"
17 | #include "base/process_util.h"
18 | #include "base/string_number_conversions.h"
19 | #include "base/string_util.h"
20 | #include "base/threading/thread.h"
21 | #include "base/time.h"
22 | #include "ipc/ipc_switches.h"
23 | #include "ipc/ipc_sync_message.h"
24 | #include "ipc/ipc_message_utils.h"
25 | #include "ipc/ipc_sender.h"
26 |
27 | #if defined(OS_POSIX)
28 | #include
29 | #endif
30 |
31 | #ifdef IPC_MESSAGE_LOG_ENABLED
32 |
33 | using base::Time;
34 |
35 | namespace IPC {
36 |
37 | const int kLogSendDelayMs = 100;
38 |
39 | // We use a pointer to the function table to avoid any linker dependencies on
40 | // all the traits used as IPC message parameters.
41 | LogFunctionMap* Logging::log_function_map_;
42 |
43 | Logging::Logging()
44 | : enabled_(false),
45 | enabled_on_stderr_(false),
46 | enabled_color_(false),
47 | queue_invoke_later_pending_(false),
48 | sender_(NULL),
49 | main_thread_(base::MessageLoop::current()),
50 | consumer_(NULL) {
51 | #if defined(OS_WIN)
52 | // getenv triggers an unsafe warning. Simply check how big of a buffer
53 | // would be needed to fetch the value to see if the enviornment variable is
54 | // set.
55 | size_t requiredSize = 0;
56 | getenv_s(&requiredSize, NULL, 0, "CHROME_IPC_LOGGING");
57 | bool logging_env_var_set = (requiredSize != 0);
58 | if (requiredSize <= 6) {
59 | char buffer[6];
60 | getenv_s(&requiredSize, buffer, sizeof(buffer), "CHROME_IPC_LOGGING");
61 | if (requiredSize && !strncmp("color", buffer, 6))
62 | enabled_color_ = true;
63 | }
64 | #else // !defined(OS_WIN)
65 | const char* ipc_logging = getenv("CHROME_IPC_LOGGING");
66 | bool logging_env_var_set = (ipc_logging != NULL);
67 | if (ipc_logging && !strcmp(ipc_logging, "color"))
68 | enabled_color_ = true;
69 | #endif //defined(OS_WIN)
70 | if (logging_env_var_set) {
71 | enabled_ = true;
72 | enabled_on_stderr_ = true;
73 | }
74 | }
75 |
76 | Logging::~Logging() {
77 | }
78 |
79 | Logging* Logging::GetInstance() {
80 | return Singleton::get();
81 | }
82 |
83 | void Logging::SetConsumer(Consumer* consumer) {
84 | consumer_ = consumer;
85 | }
86 |
87 | void Logging::Enable() {
88 | enabled_ = true;
89 | }
90 |
91 | void Logging::Disable() {
92 | enabled_ = false;
93 | }
94 |
95 | void Logging::OnSendLogs() {
96 | queue_invoke_later_pending_ = false;
97 | if (!sender_)
98 | return;
99 |
100 | Message* msg = new Message(
101 | MSG_ROUTING_CONTROL, IPC_LOGGING_ID, Message::PRIORITY_NORMAL);
102 | WriteParam(msg, queued_logs_);
103 | queued_logs_.clear();
104 | sender_->Send(msg);
105 | }
106 |
107 | void Logging::SetIPCSender(IPC::Sender* sender) {
108 | sender_ = sender;
109 | }
110 |
111 | void Logging::OnReceivedLoggingMessage(const Message& message) {
112 | std::vector data;
113 | PickleIterator iter(message);
114 | if (!ReadParam(&message, &iter, &data))
115 | return;
116 |
117 | for (size_t i = 0; i < data.size(); ++i) {
118 | Log(data[i]);
119 | }
120 | }
121 |
122 | void Logging::OnSendMessage(Message* message, const std::string& channel_id) {
123 | if (!Enabled())
124 | return;
125 |
126 | if (message->is_reply()) {
127 | LogData* data = message->sync_log_data();
128 | if (!data)
129 | return;
130 |
131 | // This is actually the delayed reply to a sync message. Create a string
132 | // of the output parameters, add it to the LogData that was earlier stashed
133 | // with the reply, and log the result.
134 | GenerateLogData("", *message, data, true);
135 | data->channel = channel_id;
136 | Log(*data);
137 | delete data;
138 | message->set_sync_log_data(NULL);
139 | } else {
140 | // If the time has already been set (i.e. by ChannelProxy), keep that time
141 | // instead as it's more accurate.
142 | if (!message->sent_time())
143 | message->set_sent_time(Time::Now().ToInternalValue());
144 | }
145 | }
146 |
147 | void Logging::OnPreDispatchMessage(const Message& message) {
148 | message.set_received_time(Time::Now().ToInternalValue());
149 | }
150 |
151 | void Logging::OnPostDispatchMessage(const Message& message,
152 | const std::string& channel_id) {
153 | if (!Enabled() ||
154 | !message.sent_time() ||
155 | !message.received_time() ||
156 | message.dont_log())
157 | return;
158 |
159 | LogData data;
160 | GenerateLogData(channel_id, message, &data, true);
161 |
162 | if (base::MessageLoop::current() == main_thread_) {
163 | Log(data);
164 | } else {
165 | main_thread_->PostTask(
166 | FROM_HERE, base::Bind(&Logging::Log, base::Unretained(this), data));
167 | }
168 | }
169 |
170 | void Logging::GetMessageText(uint32 type, std::string* name,
171 | const Message* message,
172 | std::string* params) {
173 | if (!log_function_map_)
174 | return;
175 |
176 | LogFunctionMap::iterator it = log_function_map_->find(type);
177 | if (it == log_function_map_->end()) {
178 | if (name) {
179 | *name = "[UNKNOWN MSG ";
180 | *name += base::IntToString(type);
181 | *name += " ]";
182 | }
183 | return;
184 | }
185 |
186 | (*it->second)(name, message, params);
187 | }
188 |
189 | const char* Logging::ANSIEscape(ANSIColor color) {
190 | if (!enabled_color_)
191 | return "";
192 | switch (color) {
193 | case ANSI_COLOR_RESET:
194 | return "\033[m";
195 | case ANSI_COLOR_BLACK:
196 | return "\033[0;30m";
197 | case ANSI_COLOR_RED:
198 | return "\033[0;31m";
199 | case ANSI_COLOR_GREEN:
200 | return "\033[0;32m";
201 | case ANSI_COLOR_YELLOW:
202 | return "\033[0;33m";
203 | case ANSI_COLOR_BLUE:
204 | return "\033[0;34m";
205 | case ANSI_COLOR_MAGENTA:
206 | return "\033[0;35m";
207 | case ANSI_COLOR_CYAN:
208 | return "\033[0;36m";
209 | case ANSI_COLOR_WHITE:
210 | return "\033[0;37m";
211 | }
212 | return "";
213 | }
214 |
215 | Logging::ANSIColor Logging::DelayColor(double delay) {
216 | if (delay < 0.1)
217 | return ANSI_COLOR_GREEN;
218 | if (delay < 0.25)
219 | return ANSI_COLOR_BLACK;
220 | if (delay < 0.5)
221 | return ANSI_COLOR_YELLOW;
222 | return ANSI_COLOR_RED;
223 | }
224 |
225 | void Logging::Log(const LogData& data) {
226 | if (consumer_) {
227 | // We're in the browser process.
228 | consumer_->Log(data);
229 | } else {
230 | // We're in the renderer or plugin processes.
231 | if (sender_) {
232 | queued_logs_.push_back(data);
233 | if (!queue_invoke_later_pending_) {
234 | queue_invoke_later_pending_ = true;
235 | base::MessageLoop::current()->PostDelayedTask(
236 | FROM_HERE,
237 | base::Bind(&Logging::OnSendLogs, base::Unretained(this)),
238 | base::TimeDelta::FromMilliseconds(kLogSendDelayMs));
239 | }
240 | }
241 | }
242 | if (enabled_on_stderr_) {
243 | std::string message_name;
244 | if (data.message_name.empty()) {
245 | message_name = base::StringPrintf("[unknown type %d]", data.type);
246 | } else {
247 | message_name = data.message_name;
248 | }
249 | double receive_delay =
250 | (Time::FromInternalValue(data.receive) -
251 | Time::FromInternalValue(data.sent)).InSecondsF();
252 | double dispatch_delay =
253 | (Time::FromInternalValue(data.dispatch) -
254 | Time::FromInternalValue(data.sent)).InSecondsF();
255 | fprintf(stderr,
256 | "ipc %s %d %s %s%s %s%s\n %18.5f %s%18.5f %s%18.5f%s\n",
257 | data.channel.c_str(),
258 | data.routing_id,
259 | data.flags.c_str(),
260 | ANSIEscape(sender_ ? ANSI_COLOR_BLUE : ANSI_COLOR_CYAN),
261 | message_name.c_str(),
262 | ANSIEscape(ANSI_COLOR_RESET),
263 | data.params.c_str(),
264 | Time::FromInternalValue(data.sent).ToDoubleT(),
265 | ANSIEscape(DelayColor(receive_delay)),
266 | Time::FromInternalValue(data.receive).ToDoubleT(),
267 | ANSIEscape(DelayColor(dispatch_delay)),
268 | Time::FromInternalValue(data.dispatch).ToDoubleT(),
269 | ANSIEscape(ANSI_COLOR_RESET)
270 | );
271 | }
272 | }
273 |
274 | void GenerateLogData(const std::string& channel, const Message& message,
275 | LogData* data, bool get_params) {
276 | if (message.is_reply()) {
277 | // "data" should already be filled in.
278 | std::string params;
279 | Logging::GetMessageText(data->type, NULL, &message, ¶ms);
280 |
281 | if (!data->params.empty() && !params.empty())
282 | data->params += ", ";
283 |
284 | data->flags += " DR";
285 |
286 | data->params += params;
287 | } else {
288 | std::string flags;
289 | if (message.is_sync())
290 | flags = "S";
291 |
292 | if (message.is_reply())
293 | flags += "R";
294 |
295 | if (message.is_reply_error())
296 | flags += "E";
297 |
298 | std::string params, message_name;
299 | Logging::GetMessageText(message.type(), &message_name, &message,
300 | get_params ? ¶ms : NULL);
301 |
302 | data->channel = channel;
303 | data->routing_id = message.routing_id();
304 | data->type = message.type();
305 | data->flags = flags;
306 | data->sent = message.sent_time();
307 | data->receive = message.received_time();
308 | data->dispatch = Time::Now().ToInternalValue();
309 | data->params = params;
310 | data->message_name = message_name;
311 | }
312 | }
313 |
314 | }
315 |
316 | #endif // IPC_MESSAGE_LOG_ENABLED
317 |
--------------------------------------------------------------------------------
/ipc/ipc_logging.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_LOGGING_H_
6 | #define IPC_IPC_LOGGING_H_
7 |
8 | #include "ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED.
9 |
10 | #ifdef IPC_MESSAGE_LOG_ENABLED
11 |
12 | #include
13 |
14 | #include "base/hash_tables.h"
15 | #include "base/memory/scoped_ptr.h"
16 | #include "base/memory/singleton.h"
17 | #include "base/message_loop.h"
18 | #include "ipc/ipc_export.h"
19 |
20 | // Logging function. |name| is a string in ASCII and |params| is a string in
21 | // UTF-8.
22 | typedef void (*LogFunction)(std::string* name,
23 | const IPC::Message* msg,
24 | std::string* params);
25 |
26 | typedef base::hash_map LogFunctionMap;
27 |
28 | namespace IPC {
29 |
30 | class Message;
31 | class Sender;
32 |
33 | // One instance per process. Needs to be created on the main thread (the UI
34 | // thread in the browser) but OnPreDispatchMessage/OnPostDispatchMessage
35 | // can be called on other threads.
36 | class IPC_EXPORT Logging {
37 | public:
38 | // Implemented by consumers of log messages.
39 | class Consumer {
40 | public:
41 | virtual void Log(const LogData& data) = 0;
42 |
43 | protected:
44 | virtual ~Consumer() {}
45 | };
46 |
47 | void SetConsumer(Consumer* consumer);
48 |
49 | ~Logging();
50 | static Logging* GetInstance();
51 |
52 | // Enable and Disable are NOT cross-process; they only affect the
53 | // current thread/process. If you want to modify the value for all
54 | // processes, perhaps your intent is to call
55 | // g_browser_process->SetIPCLoggingEnabled().
56 | void Enable();
57 | void Disable();
58 | bool Enabled() const { return enabled_; }
59 |
60 | // Called by child processes to give the logger object the channel to send
61 | // logging data to the browser process.
62 | void SetIPCSender(Sender* sender);
63 |
64 | // Called in the browser process when logging data from a child process is
65 | // received.
66 | void OnReceivedLoggingMessage(const Message& message);
67 |
68 | void OnSendMessage(Message* message, const std::string& channel_id);
69 | void OnPreDispatchMessage(const Message& message);
70 | void OnPostDispatchMessage(const Message& message,
71 | const std::string& channel_id);
72 |
73 | // Like the *MsgLog functions declared for each message class, except this
74 | // calls the correct one based on the message type automatically. Defined in
75 | // ipc_logging.cc.
76 | static void GetMessageText(uint32 type, std::string* name,
77 | const Message* message, std::string* params);
78 |
79 | static void set_log_function_map(LogFunctionMap* functions) {
80 | log_function_map_ = functions;
81 | }
82 |
83 | static LogFunctionMap* log_function_map() {
84 | return log_function_map_;
85 | }
86 |
87 | private:
88 | typedef enum {
89 | ANSI_COLOR_RESET = -1,
90 | ANSI_COLOR_BLACK,
91 | ANSI_COLOR_RED,
92 | ANSI_COLOR_GREEN,
93 | ANSI_COLOR_YELLOW,
94 | ANSI_COLOR_BLUE,
95 | ANSI_COLOR_MAGENTA,
96 | ANSI_COLOR_CYAN,
97 | ANSI_COLOR_WHITE
98 | } ANSIColor;
99 | const char* ANSIEscape(ANSIColor color);
100 | ANSIColor DelayColor(double delay);
101 |
102 | friend struct DefaultSingletonTraits;
103 | Logging();
104 |
105 | void OnSendLogs();
106 | void Log(const LogData& data);
107 |
108 | bool enabled_;
109 | bool enabled_on_stderr_; // only used on POSIX for now
110 | bool enabled_color_; // only used on POSIX for now
111 |
112 | std::vector queued_logs_;
113 | bool queue_invoke_later_pending_;
114 |
115 | Sender* sender_;
116 | base::MessageLoop* main_thread_;
117 |
118 | Consumer* consumer_;
119 |
120 | static LogFunctionMap* log_function_map_;
121 | };
122 |
123 | } // namespace IPC
124 |
125 | #endif // IPC_MESSAGE_LOG_ENABLED
126 |
127 | #endif // IPC_IPC_LOGGING_H_
128 |
--------------------------------------------------------------------------------
/ipc/ipc_message.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "ipc/ipc_message.h"
6 |
7 | #include
8 | #include
9 |
10 | namespace {
11 |
12 | int32 g_ref_num = 0;
13 |
14 | const int kPayloadUnit = 32;
15 |
16 | const size_t kCapacityReadOnly = static_cast(-1);
17 |
18 |
19 |
20 | // Create a reference number for identifying IPC messages in traces. The return
21 | // values has the reference number stored in the upper 24 bits, leaving the low
22 | // 8 bits set to 0 for use as flags.
23 | inline uint32 GetRefNumUpper24() {
24 | int32 pid = 0;
25 | int32 count = InterlockedExchangeAdd(reinterpret_cast(&g_ref_num), 1);
26 | // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
27 | // Process ID. With the current trace event buffer cap, the 14-bit count did
28 | // not appear to wrap during a trace. Note that it is not a big deal if
29 | // collisions occur, as this is only used for debugging and trace analysis.
30 | return ((pid << 14) | (count & 0x3fff)) << 8;
31 | }
32 |
33 | } // namespace
34 |
35 | namespace IPC {
36 |
37 | const uint32 Message::kHeaderSize = sizeof(Message::Header);
38 |
39 | //------------------------------------------------------------------------------
40 |
41 | Message::~Message() {
42 | if (capacity_ != kCapacityReadOnly)
43 | free(header_);
44 | }
45 |
46 | Message::Message()
47 | : header_(NULL)
48 | , capacity_(0)
49 | , ref_count_(0)
50 | , variable_buffer_offset_(0) {
51 | Resize(kPayloadUnit);
52 |
53 | header()->payload_size = 0;
54 | header()->routing = header()->type = 0;
55 | header()->flags = GetRefNumUpper24();
56 |
57 |
58 |
59 | InitLoggingVariables();
60 | }
61 |
62 | Message::Message(int32 routing_id, uint32 type, PriorityValue priority)
63 | : header_(NULL)
64 | , capacity_(0)
65 | , ref_count_(0)
66 | , variable_buffer_offset_(0) {
67 | Resize(kPayloadUnit);
68 |
69 | header()->payload_size = 0;
70 | header()->routing = routing_id;
71 | header()->type = type;
72 | assert((priority & 0xffffff00) == 0);
73 | header()->flags = priority | GetRefNumUpper24();
74 |
75 |
76 | InitLoggingVariables();
77 | }
78 |
79 | Message::Message(const char* data, int data_len)
80 | : header_(reinterpret_cast(const_cast(data)))
81 | , capacity_(kCapacityReadOnly)
82 | , ref_count_(0)
83 | , variable_buffer_offset_(0) {
84 |
85 | if (kHeaderSize > static_cast(data_len))
86 | header_ = NULL;
87 |
88 | if (header_ && header_->payload_size + kHeaderSize > static_cast(data_len))
89 | header_ = NULL;
90 |
91 | InitLoggingVariables();
92 | }
93 |
94 | void Message::InitLoggingVariables() {
95 | #ifdef IPC_MESSAGE_LOG_ENABLED
96 | received_time_ = 0;
97 | dont_log_ = false;
98 | log_data_ = NULL;
99 | #endif
100 | }
101 |
102 | void Message::SetHeaderValues(int32 routing, uint32 type, uint32 flags) {
103 | // This should only be called when the message is already empty.
104 | assert(payload_size() == 0);
105 |
106 | header()->routing = routing;
107 | header()->type = type;
108 | header()->flags = flags;
109 | }
110 |
111 | #ifdef IPC_MESSAGE_LOG_ENABLED
112 | void Message::set_sent_time(int64 time) {
113 | DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
114 | header()->flags |= HAS_SENT_TIME_BIT;
115 | WriteInt64(time);
116 | }
117 |
118 | int64 Message::sent_time() const {
119 | if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
120 | return 0;
121 |
122 | const char* data = end_of_payload();
123 | data -= sizeof(int64);
124 | return *(reinterpret_cast(data));
125 | }
126 |
127 | void Message::set_received_time(int64 time) const {
128 | received_time_ = time;
129 | }
130 | #endif
131 |
132 | Message::Header* Message::header()
133 | {
134 | return static_cast(header_);
135 | }
136 |
137 | const Message::Header* Message::header() const
138 | {
139 | return static_cast(header_);
140 | }
141 |
142 | bool Message::Resize(size_t new_capacity)
143 | {
144 | new_capacity = AlignInt(new_capacity, kPayloadUnit);
145 |
146 | assert(capacity_ != kCapacityReadOnly);
147 | void* p = realloc(header_, new_capacity);
148 | if (!p)
149 | return false;
150 |
151 | header_ = reinterpret_cast(p);
152 | capacity_ = new_capacity;
153 | return true;
154 | }
155 |
156 | const char* Message::FindNext(const char* range_start, const char* range_end)
157 | {
158 | if (static_cast(range_end - range_start) < sizeof(Header))
159 | return NULL;
160 |
161 | const Header* hdr = reinterpret_cast(range_start);
162 | const char* payload_base = range_start + sizeof(Header);
163 | const char* payload_end = payload_base + hdr->payload_size;
164 | if (payload_end < payload_base)
165 | return NULL;
166 |
167 | return (payload_end > range_end) ? NULL : payload_end;
168 | }
169 |
170 | bool Message::WriteString(const std::string& value)
171 | {
172 | if(!WriteInt(static_cast(value.size())))
173 | return false;
174 |
175 | return WriteBytes(value.data(), static_cast(value.size()));
176 | }
177 |
178 | bool Message::WriteString(const std::wstring& value)
179 | {
180 | if (!WriteInt(static_cast(value.size())))
181 | return false;
182 |
183 | return WriteBytes(value.data(),
184 | static_cast(value.size() * sizeof(wchar_t)));
185 | }
186 |
187 | bool Message::WriteData(const char* data, int length)
188 | {
189 | return length >= 0 && WriteInt(length) && WriteBytes(data, length);
190 | }
191 |
192 | bool Message::WriteBytes(const void* data, int data_len)
193 | {
194 | assert(kCapacityReadOnly != capacity_);
195 |
196 | size_t offset = header_->payload_size;
197 |
198 | size_t new_size = offset + data_len;
199 | size_t needed_size = sizeof(Header) + new_size;
200 | if (needed_size > capacity_ && !Resize((std::max)(capacity_ * 2, needed_size)))
201 | return false;
202 |
203 | header_->payload_size = static_cast(new_size);
204 | char* dest = const_cast(payload()) + offset;
205 | memcpy(dest, data, data_len);
206 | return true;
207 | }
208 |
209 | void Message::AddRef() const
210 | {
211 | InterlockedIncrement(&ref_count_);
212 | }
213 |
214 | void Message::Release() const
215 | {
216 | if (InterlockedDecrement(&ref_count_) == 0)
217 | {
218 | delete this;
219 | }
220 | }
221 |
222 |
223 | MessageReader::MessageReader(Message* m)
224 | : read_ptr_(m->payload())
225 | , read_end_ptr_(m->end_of_payload())
226 | {
227 |
228 | }
229 |
230 | template
231 | inline bool MessageReader::ReadBuiltinType(Type* result) {
232 | const char* read_from = GetReadPointerAndAdvance(sizeof(Type));
233 | if (!read_from)
234 | return false;
235 | memcpy(result, read_from, sizeof(*result));
236 | return true;
237 | }
238 |
239 | const char* MessageReader::GetReadPointerAndAdvance(int num_bytes) {
240 | if (num_bytes < 0 || read_end_ptr_ - read_ptr_ < num_bytes)
241 | return NULL;
242 | const char* current_read_ptr = read_ptr_;
243 | read_ptr_ += num_bytes;
244 | return current_read_ptr;
245 | }
246 |
247 | const char* MessageReader::GetReadPointerAndAdvance(int num_elements, size_t size_element)
248 | {
249 | // Check for int32 overflow.
250 | int64 num_bytes = static_cast(num_elements)* size_element;
251 | int num_bytes32 = static_cast(num_bytes);
252 | if (num_bytes != static_cast(num_bytes32))
253 | return NULL;
254 | return GetReadPointerAndAdvance(num_bytes32);
255 | }
256 |
257 | bool MessageReader::ReadBool(bool* result)
258 | {
259 | return ReadBuiltinType(result);
260 | }
261 |
262 | bool MessageReader::ReadInt(int* result)
263 | {
264 | return ReadBuiltinType(result);
265 | }
266 |
267 | bool MessageReader::ReadUInt16(uint16* result)
268 | {
269 | return ReadBuiltinType(result);
270 | }
271 |
272 | bool MessageReader::ReadUInt32(uint32* result)
273 | {
274 | return ReadBuiltinType(result);
275 | }
276 |
277 | bool MessageReader::ReadInt64(int64* result)
278 | {
279 | return ReadBuiltinType(result);
280 | }
281 |
282 | bool MessageReader::ReadUInt64(uint64* result)
283 | {
284 | return ReadBuiltinType(result);
285 | }
286 |
287 | bool MessageReader::ReadFloat(float* result)
288 | {
289 | return ReadBuiltinType(result);
290 | }
291 |
292 | bool MessageReader::ReadString(std::string* result)
293 | {
294 | int len;
295 | if (!ReadInt(&len))
296 | return false;
297 | const char* read_from = GetReadPointerAndAdvance(len);
298 | if (!read_from)
299 | return false;
300 |
301 | result->assign(read_from, len);
302 | return true;
303 | }
304 |
305 | bool MessageReader::ReadWString(std::wstring* result)
306 | {
307 | int len;
308 | if (!ReadInt(&len))
309 | return false;
310 | const char* read_from = GetReadPointerAndAdvance(len, sizeof(wchar_t));
311 | if (!read_from)
312 | return false;
313 |
314 | result->assign(reinterpret_cast(read_from), len);
315 | return true;
316 | }
317 |
318 | bool MessageReader::ReadData(const char** data, int* length)
319 | {
320 | *length = 0;
321 | *data = 0;
322 |
323 | if (!ReadInt(length))
324 | return false;
325 |
326 | return ReadBytes(data, *length);
327 | }
328 |
329 | bool MessageReader::ReadBytes(const char** data, int length)
330 | {
331 | const char* read_from = GetReadPointerAndAdvance(length);
332 | if (!read_from)
333 | return false;
334 | *data = read_from;
335 | return true;
336 | }
337 |
338 | } // namespace IPC
339 |
--------------------------------------------------------------------------------
/ipc/ipc_message.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hicdre/AsyncIpc/8253b2bad7a6f17f972294827ae13df47292f047/ipc/ipc_message.h
--------------------------------------------------------------------------------
/ipc/ipc_sender.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #ifndef IPC_IPC_SENDER_H_
6 | #define IPC_IPC_SENDER_H_
7 |
8 | namespace IPC {
9 |
10 | class Message;
11 |
12 | class Sender {
13 | public:
14 | // Sends the given IPC message. The implementor takes ownership of the
15 | // given Message regardless of whether or not this method succeeds. This
16 | // is done to make this method easier to use. Returns true on success and
17 | // false otherwise.
18 | virtual bool Send(Message* msg) = 0;
19 |
20 | protected:
21 | virtual ~Sender() {}
22 | };
23 |
24 | } // namespace IPC
25 |
26 | #endif // IPC_IPC_SENDER_H_
27 |
--------------------------------------------------------------------------------
/ipc/ipc_thread.cpp:
--------------------------------------------------------------------------------
1 | #include "ipc_thread.h"
2 | #include
3 |
4 | namespace IPC
5 | {
6 | Thread::Thread()
7 | : thread_(NULL)
8 | , should_quit_(false)
9 | {
10 | io_port_ = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
11 | }
12 |
13 | Thread::~Thread()
14 | {
15 | ::CloseHandle(io_port_);
16 | }
17 |
18 | void Thread::RegisterIOHandler(HANDLE file, IOHandler* handler)
19 | {
20 | ULONG_PTR key = HandlerToKey(handler, true);
21 | HANDLE port = CreateIoCompletionPort(file, io_port_, key, 1);
22 | assert(port);
23 | }
24 |
25 | ULONG_PTR Thread::HandlerToKey(IOHandler* handler, bool has_valid_io_context)
26 | {
27 | ULONG_PTR key = reinterpret_cast(handler);
28 |
29 | // |IOHandler| is at least pointer-size aligned, so the lowest two bits are
30 | // always cleared. We use the lowest bit to distinguish completion keys with
31 | // and without the associated |IOContext|.
32 | assert((key & 1) == 0);
33 |
34 | // Mark the completion key as context-less.
35 | if (!has_valid_io_context)
36 | key = key | 1;
37 | return key;
38 | }
39 |
40 | Thread::IOHandler* Thread::KeyToHandler(ULONG_PTR key, bool* has_valid_io_context)
41 | {
42 | *has_valid_io_context = ((key & 1) == 0);
43 | return reinterpret_cast(key & ~static_cast(1));
44 | }
45 |
46 | void Thread::PostTask(const Task& task)
47 | {
48 | {
49 | AutoLock lock(task_mutex_);
50 | task_queue_.push_back(task);
51 | }
52 | ScheduleWork();
53 | }
54 |
55 | void Thread::Start()
56 | {
57 | if (thread_ == NULL)
58 | {
59 | should_quit_ = false;
60 | thread_ = ::CreateThread(0, 0, IOThreadMain, this, 0, 0);
61 | }
62 | }
63 |
64 |
65 | void Thread::Stop()
66 | {
67 | should_quit_ = true;
68 |
69 | if (thread_)
70 | {
71 | ::WaitForSingleObject(thread_, 1000);
72 | CloseHandle(thread_);
73 | thread_ = NULL;
74 | }
75 | }
76 |
77 |
78 | void Thread::Wait(DWORD timeout)
79 | {
80 | ::WaitForSingleObject(thread_, timeout);
81 | }
82 |
83 |
84 |
85 | DWORD WINAPI Thread::IOThreadMain(LPVOID params)
86 | {
87 | reinterpret_cast(params)->Run();
88 | return 0;
89 | }
90 |
91 | void Thread::Run()
92 | {
93 | for (;;) {
94 |
95 | bool more_work_is_plausible = DoScheduledWork();
96 |
97 | if (should_quit_)
98 | break;
99 |
100 | more_work_is_plausible |= WaitForIOCompletion(0, NULL);
101 |
102 | if (should_quit_)
103 | break;
104 |
105 | if (more_work_is_plausible)
106 | continue;
107 |
108 | if (should_quit_)
109 | break;
110 |
111 | WaitForWork(); // Wait (sleep) until we have work to do again.
112 | }
113 | }
114 |
115 | bool Thread::DoScheduledWork()
116 | {
117 | std::deque work_queue;
118 | {
119 | AutoLock lock(task_mutex_);
120 | if (task_queue_.empty())
121 | return false;
122 | work_queue.swap(task_queue_);
123 | }
124 |
125 | do
126 | {
127 | Task t = work_queue.front();
128 | work_queue.pop_front();
129 |
130 | t();
131 | } while (!work_queue.empty());
132 |
133 | return false;
134 | }
135 |
136 | bool Thread::WaitForIOCompletion(DWORD timeout, IOHandler* filter)
137 | {
138 | IOItem item;
139 | if (completed_io_.empty() || !MatchCompletedIOItem(filter, &item)) {
140 | // We have to ask the system for another IO completion.
141 | if (!GetIOItem(timeout, &item))
142 | return false;
143 |
144 | if (ProcessInternalIOItem(item))
145 | return true;
146 | }
147 |
148 | // If |item.has_valid_io_context| is false then |item.context| does not point
149 | // to a context structure, and so should not be dereferenced, although it may
150 | // still hold valid non-pointer data.
151 | if (!item.has_valid_io_context || item.context->handler) {
152 | if (filter && item.handler != filter) {
153 | // Save this item for later
154 | completed_io_.push_back(item);
155 | }
156 | else {
157 | assert(!item.has_valid_io_context ||
158 | (item.context->handler == item.handler));
159 | item.handler->OnIOCompleted(item.context, item.bytes_transfered,
160 | item.error);
161 | }
162 | }
163 | else {
164 | // The handler must be gone by now, just cleanup the mess.
165 | delete item.context;
166 | }
167 | return true;
168 | }
169 |
170 | void Thread::WaitForWork()
171 | {
172 | int timeout;
173 | timeout = INFINITE;
174 | WaitForIOCompletion(timeout, NULL);
175 | }
176 |
177 | bool Thread::MatchCompletedIOItem(IOHandler* filter, IOItem* item)
178 | {
179 | for (std::list::iterator it = completed_io_.begin();
180 | it != completed_io_.end(); ++it) {
181 | if (!filter || it->handler == filter) {
182 | *item = *it;
183 | completed_io_.erase(it);
184 | return true;
185 | }
186 | }
187 | return false;
188 | }
189 |
190 | bool Thread::GetIOItem(DWORD timeout, IOItem* item)
191 | {
192 | memset(item, 0, sizeof(*item));
193 | ULONG_PTR key = NULL;
194 | OVERLAPPED* overlapped = NULL;
195 | if (!GetQueuedCompletionStatus(io_port_, &item->bytes_transfered, &key,
196 | &overlapped, timeout)) {
197 | if (!overlapped)
198 | return false; // Nothing in the queue.
199 | item->error = GetLastError();
200 | item->bytes_transfered = 0;
201 | }
202 |
203 | item->handler = KeyToHandler(key, &item->has_valid_io_context);
204 | item->context = reinterpret_cast(overlapped);
205 | return true;
206 | }
207 |
208 | bool Thread::ProcessInternalIOItem(const IOItem& item)
209 | {
210 | if (this == reinterpret_cast(item.context) &&
211 | this == reinterpret_cast(item.handler)) {
212 | // This is our internal completion.
213 | assert(!item.bytes_transfered);
214 | return true;
215 | }
216 | return false;
217 | }
218 |
219 | void Thread::ScheduleWork()
220 | {
221 | PostQueuedCompletionStatus(io_port_, 0,
222 | reinterpret_cast(this),
223 | reinterpret_cast(this));
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/ipc/ipc_thread.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ipc/ipc_common.h"
3 | #include "ipc/ipc_utils.h"
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | namespace IPC
10 | {
11 | class Thread
12 | {
13 | public:
14 | typedef std::function Task;
15 |
16 | struct IOContext;
17 |
18 | class IOHandler {
19 | public:
20 | virtual ~IOHandler() {}
21 | // This will be called once the pending IO operation associated with
22 | // |context| completes. |error| is the Win32 error code of the IO operation
23 | // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero
24 | // on error.
25 | virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered,
26 | DWORD error) = 0;
27 | };
28 |
29 | struct IOContext {
30 | OVERLAPPED overlapped;
31 | IOHandler* handler;
32 | };
33 |
34 | Thread();
35 | ~Thread();
36 |
37 | void Start();
38 | void Stop();
39 | void Wait(DWORD timeout);
40 |
41 | void RegisterIOHandler(HANDLE file, IOHandler* handler);
42 | bool WaitForIOCompletion(DWORD timeout, IOHandler* filter);
43 |
44 | void PostTask(const Task& task);
45 | private:
46 | struct IOItem {
47 | IOHandler* handler;
48 | IOContext* context;
49 | DWORD bytes_transfered;
50 | DWORD error;
51 |
52 | // In some cases |context| can be a non-pointer value casted to a pointer.
53 | // |has_valid_io_context| is true if |context| is a valid IOContext
54 | // pointer, and false otherwise.
55 | bool has_valid_io_context;
56 | };
57 |
58 | static DWORD WINAPI IOThreadMain(LPVOID params);
59 | // Converts an IOHandler pointer to a completion port key.
60 | // |has_valid_io_context| specifies whether completion packets posted to
61 | // |handler| will have valid OVERLAPPED pointers.
62 | static ULONG_PTR HandlerToKey(IOHandler* handler, bool has_valid_io_context);
63 | static IOHandler* KeyToHandler(ULONG_PTR key, bool* has_valid_io_context);
64 |
65 | void Run();
66 | bool DoScheduledWork();
67 | void ScheduleWork();
68 | void WaitForWork();
69 |
70 | bool MatchCompletedIOItem(IOHandler* filter, IOItem* item);
71 | bool GetIOItem(DWORD timeout, IOItem* item);
72 | bool ProcessInternalIOItem(const IOItem& item);
73 | void WillProcessIOEvent();
74 | void DidProcessIOEvent();
75 |
76 | HANDLE thread_;
77 | bool should_quit_;
78 |
79 | HANDLE io_port_;
80 | std::list completed_io_;
81 |
82 | Lock task_mutex_;
83 | std::deque task_queue_;
84 | };
85 | }
--------------------------------------------------------------------------------
/ipc/ipc_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "ipc_utils.h"
2 | #include
3 | #include
4 |
5 | Lock::Lock()
6 | {
7 | ::InitializeCriticalSectionAndSpinCount(&cs, 2000);
8 | }
9 |
10 | Lock::~Lock()
11 | {
12 | ::DeleteCriticalSection(&cs);
13 | }
14 |
15 | bool Lock::Try()
16 | {
17 | if (::TryEnterCriticalSection(&cs) != FALSE) {
18 | return true;
19 | }
20 | return false;
21 | }
22 |
23 | void Lock::Dolock()
24 | {
25 | ::EnterCriticalSection(&cs);
26 | }
27 |
28 | void Lock::Unlock()
29 | {
30 | ::LeaveCriticalSection(&cs);
31 | }
32 |
33 | AutoLock::AutoLock(Lock& m)
34 | : m_(m)
35 | {
36 | m_.Dolock();
37 | }
38 |
39 | AutoLock::~AutoLock()
40 | {
41 | m_.Unlock();
42 | }
43 |
44 | uint32 RandUint32() {
45 | uint32 number;
46 | rand_s(&number);
47 | return number;
48 | }
49 |
50 | uint64 RandUint64() {
51 | uint32 first_half = RandUint32();
52 | uint32 second_half = RandUint32();
53 | return (static_cast(first_half) << 32) + second_half;
54 | }
55 |
56 | int RandInt(int min, int max)
57 | {
58 | assert(min < max);
59 |
60 | uint64 range = static_cast(max)-min + 1;
61 | int result = min + static_cast(RandGenerator(range));
62 | return result;
63 | }
64 |
65 | uint64 RandGenerator(uint64 range)
66 | {
67 | assert(range > 0u);
68 | // We must discard random results above this number, as they would
69 | // make the random generator non-uniform (consider e.g. if
70 | // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
71 | // as likely as a result of 3 or 4).
72 | uint64 max_acceptable_value =
73 | ((std::numeric_limits::max)() / range) * range - 1;
74 |
75 | uint64 value;
76 | do {
77 | value = RandUint64();
78 | } while (value > max_acceptable_value);
79 |
80 | return value % range;
81 | }
82 |
83 | std::wstring ASCIIToWide(const std::string& mb)
84 | {
85 | if (mb.empty())
86 | return std::wstring();
87 |
88 | int mb_length = static_cast(mb.length());
89 | // Compute the length of the buffer.
90 | int charcount = MultiByteToWideChar(CP_UTF8, 0,
91 | mb.data(), mb_length, NULL, 0);
92 | if (charcount == 0)
93 | return std::wstring();
94 |
95 | std::wstring wide;
96 | wide.resize(charcount);
97 | MultiByteToWideChar(CP_UTF8, 0, mb.data(), mb_length, &wide[0], charcount);
98 |
99 | return wide;
100 | }
101 |
--------------------------------------------------------------------------------
/ipc/ipc_utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ipc/ipc_common.h"
3 |
4 | class Lock
5 | {
6 | public:
7 | Lock();
8 | ~Lock();
9 |
10 | bool Try();
11 |
12 | // Take the lock, blocking until it is available if necessary.
13 | void Dolock();
14 |
15 | // Release the lock. This must only be called by the lock's holder: after
16 | // a successful call to Try, or a call to Lock.
17 | void Unlock();
18 |
19 | private:
20 | CRITICAL_SECTION cs;
21 | DISALLOW_COPY_AND_ASSIGN(Lock);
22 | };
23 |
24 | class AutoLock
25 | {
26 | public:
27 | explicit AutoLock(Lock& m);
28 | ~AutoLock();
29 |
30 | private:
31 | Lock& m_;
32 | DISALLOW_COPY_AND_ASSIGN(AutoLock);
33 | };
34 |
35 | class StaticAtomicSequenceNumber {
36 | public:
37 | inline int GetNext() {
38 | return static_cast(
39 | InterlockedExchangeAdd(reinterpret_cast(&seq_), 1));
40 | }
41 |
42 | private:
43 | friend class AtomicSequenceNumber;
44 |
45 | inline void Reset() {
46 | seq_ = 0;
47 | }
48 |
49 | int32 seq_;
50 | };
51 |
52 | template
53 | class scoped_refptr
54 | {
55 | public:
56 | scoped_refptr(T* t)
57 | {
58 | p_ = t;
59 | if (p_)
60 | p_->AddRef();
61 | }
62 | ~scoped_refptr()
63 | {
64 | Clear();
65 | }
66 | scoped_refptr(const scoped_refptr& r) : p_(r.p_) {
67 | if (p_)
68 | p_->AddRef();
69 | }
70 | void Clear()
71 | {
72 | if (p_)
73 | p_->Release();
74 | }
75 | T* operator->() const
76 | {
77 | return p_;
78 | }
79 | T* get() const
80 | {
81 | return p_;
82 | }
83 |
84 |
85 | private:
86 | T* p_;
87 | };
88 |
89 | int RandInt(int min, int max);
90 |
91 | uint64 RandGenerator(uint64 range);
92 |
93 | std::wstring ASCIIToWide(const std::string& str);
--------------------------------------------------------------------------------
/ipc/stdafx.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
--------------------------------------------------------------------------------
/ipc/stdafx.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define _CRT_RAND_S
4 | #define _CRT_SECURE_NO_WARNINGS
5 |
6 | #include
7 | #include
8 |
9 |
10 | #include
--------------------------------------------------------------------------------
/ipc_dll/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | DYNAMIC LINK LIBRARY : ipc_dll Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this ipc_dll DLL for you.
6 |
7 | This file contains a summary of what you will find in each of the files that
8 | make up your ipc_dll application.
9 |
10 |
11 | ipc_dll.vcxproj
12 | This is the main project file for VC++ projects generated using an Application Wizard.
13 | It contains information about the version of Visual C++ that generated the file, and
14 | information about the platforms, configurations, and project features selected with the
15 | Application Wizard.
16 |
17 | ipc_dll.vcxproj.filters
18 | This is the filters file for VC++ projects generated using an Application Wizard.
19 | It contains information about the association between the files in your project
20 | and the filters. This association is used in the IDE to show grouping of files with
21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
22 | "Source Files" filter).
23 |
24 | ipc_dll.cpp
25 | This is the main DLL source file.
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | Other standard files:
29 |
30 | StdAfx.h, StdAfx.cpp
31 | These files are used to build a precompiled header (PCH) file
32 | named ipc_dll.pch and a precompiled types file named StdAfx.obj.
33 |
34 | /////////////////////////////////////////////////////////////////////////////
35 | Other notes:
36 |
37 | AppWizard uses "TODO:" comments to indicate parts of the source code you
38 | should add to or customize.
39 |
40 | /////////////////////////////////////////////////////////////////////////////
41 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_dll.cpp:
--------------------------------------------------------------------------------
1 | // ipc_dll.cpp : Defines the exported functions for the DLL application.
2 | //
3 |
4 | #include "stdafx.h"
5 | #include "ipc_dll.h"
6 | #include "ipc_factory_impl.h"
7 |
8 |
9 | IPC::FactoryImpl* gFactory = NULL;
10 |
11 | bool GetIPCEndPoint(void** instance, const char* name, void* listener /*= 0*/)
12 | {
13 | if (!gFactory)
14 | return false;
15 | IPC::IEndpoint* endpoint = gFactory->GetEndPoint(name, (IPC::IListener*)listener);
16 | *instance = endpoint;
17 | return !!endpoint;
18 | }
19 |
20 |
21 | BOOL APIENTRY DllMain(HMODULE hModule,
22 | DWORD ul_reason_for_call,
23 | LPVOID lpReserved
24 | )
25 | {
26 | switch (ul_reason_for_call)
27 | {
28 | case DLL_PROCESS_ATTACH:
29 | gFactory = new IPC::FactoryImpl;
30 | break;
31 | case DLL_THREAD_ATTACH:
32 | case DLL_THREAD_DETACH:
33 | break;
34 | case DLL_PROCESS_DETACH:
35 | if (gFactory)
36 | {
37 | delete gFactory;
38 | gFactory = NULL;
39 | }
40 | break;
41 | }
42 | return TRUE;
43 | }
44 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_dll.def:
--------------------------------------------------------------------------------
1 | LIBRARY
2 | EXPORTS
3 | GetIPCEndPoint @ 1
4 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_dll.h:
--------------------------------------------------------------------------------
1 | // The following ifdef block is the standard way of creating macros which make exporting
2 | // from a DLL simpler. All files within this DLL are compiled with the IPC_DLL_EXPORTS
3 | // symbol defined on the command line. This symbol should not be defined on any project
4 | // that uses this DLL. This way any other project whose source files include this file see
5 | // IPC_DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
6 | // defined with this macro as being exported.
7 |
8 | __declspec(dllexport) bool GetIPCEndPoint(void** instance, const char* name, void* listener = 0);
9 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_dll.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {A808021A-C2FF-4B8D-A24A-B3535BCA0637}
15 | Win32Proj
16 | ipc_dll
17 |
18 |
19 |
20 | DynamicLibrary
21 | true
22 | v120_xp
23 | Unicode
24 |
25 |
26 | DynamicLibrary
27 | false
28 | v120_xp
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 | ..\output\$(Configuration)\
45 | ..\build\$(ProjectName)\$(Configuration)\
46 |
47 |
48 | false
49 | ..\output\$(Configuration)\
50 | ..\build\$(ProjectName)\$(Configuration)\
51 |
52 |
53 |
54 | Use
55 | Level3
56 | Disabled
57 | WIN32;_DEBUG;_WINDOWS;_USRDLL;IPC_DLL_EXPORTS;%(PreprocessorDefinitions)
58 | true
59 | $(projectdir)..;%(AdditionalIncludeDirectories)
60 |
61 |
62 | Windows
63 | true
64 | ipc_dll.def
65 |
66 |
67 |
68 |
69 | Level3
70 | Use
71 | MaxSpeed
72 | true
73 | true
74 | WIN32;NDEBUG;_WINDOWS;_USRDLL;IPC_DLL_EXPORTS;%(PreprocessorDefinitions)
75 | true
76 | $(projectdir)..;%(AdditionalIncludeDirectories)
77 |
78 |
79 | Windows
80 | true
81 | true
82 | true
83 | ipc_dll.def
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | Create
103 | Create
104 |
105 |
106 |
107 |
108 | {896c53b4-9517-429a-911c-1a2b634b8319}
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_dll.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 |
41 |
42 | Source Files
43 |
44 |
45 | Source Files
46 |
47 |
48 | Source Files
49 |
50 |
51 | Source Files
52 |
53 |
54 |
55 |
56 | Source Files
57 |
58 |
59 |
--------------------------------------------------------------------------------
/ipc_dll/ipc_endpoint_impl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ipc_endpoint_impl.h"
3 | #include "ipc/ipc_message.h"
4 | #include
5 |
6 | namespace IPC
7 | {
8 |
9 |
10 | EndpointImpl::EndpointImpl(const std::string& name, IListener* listener)
11 | : endpoint_(new Endpoint(name, this))
12 | {
13 | listener_ = listener;
14 | if (listener_)
15 | listener_->AddRef();
16 | }
17 |
18 | EndpointImpl::~EndpointImpl()
19 | {
20 | assert(endpoint_);
21 | delete endpoint_;
22 | endpoint_ = NULL;
23 |
24 | if (listener_)
25 | listener_->Release();
26 | }
27 |
28 | void EndpointImpl::AddRef() const
29 | {
30 | InterlockedIncrement(&ref_count_);
31 | }
32 |
33 | void EndpointImpl::Release() const
34 | {
35 | if (InterlockedDecrement(&ref_count_) == 0)
36 | {
37 | delete this;
38 | }
39 | }
40 |
41 | IPC::ErrorCode EndpointImpl::Send(const char* message, size_t len)
42 | {
43 | scoped_refptr m(new Message);
44 | m->WriteString(std::string(message, len));
45 | return endpoint_->Send(m.get()) ? ERROR_OK : ERROR_DEST_DISCONNECTED;
46 | }
47 |
48 | void EndpointImpl::SetListener(IListener* listener)
49 | {
50 | AutoLock lock(lock_);
51 | if (listener_)
52 | listener_->Release();
53 | listener_ = listener;
54 | if (listener_)
55 | listener_->AddRef();
56 | }
57 |
58 |
59 | bool EndpointImpl::HasListener() const
60 | {
61 | AutoLock lock(lock_);
62 | return listener_ != NULL;
63 | }
64 |
65 |
66 | bool EndpointImpl::OnMessageReceived(Message* message)
67 | {
68 | std::string s;
69 | MessageReader reader(message);
70 | if (!reader.ReadString(&s))
71 | return true;
72 | AutoLock lock(lock_);
73 | if (listener_)
74 | listener_->OnMessageReceived(s.c_str(), s.size());
75 | return true;
76 | }
77 |
78 | void EndpointImpl::OnChannelConnected(int32 peer_pid)
79 | {
80 | AutoLock lock(lock_);
81 | if (listener_)
82 | listener_->OnDestConnected(peer_pid);
83 | }
84 |
85 | void EndpointImpl::OnChannelError()
86 | {
87 | AutoLock lock(lock_);
88 | if (listener_)
89 | listener_->OnDestDisconnected();
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/ipc_dll/ipc_endpoint_impl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ipc/ipc_interface.h"
3 | #include "ipc/ipc_endpoint.h"
4 | #include
5 |
6 | namespace IPC
7 | {
8 | class EndpointImpl : public IEndpoint, public Listener
9 | {
10 | public:
11 | EndpointImpl(const std::string& name, IListener* listener);
12 | ~EndpointImpl();
13 | virtual void AddRef() const override;
14 | virtual void Release() const override;
15 | virtual ErrorCode Send(const char* message, size_t len) override;
16 | virtual void SetListener(IListener* listener) override;
17 | virtual bool HasListener() const override;
18 | private:
19 | virtual bool OnMessageReceived(Message* message) override;
20 | virtual void OnChannelConnected(int32 peer_pid) override;
21 | virtual void OnChannelError() override;
22 | private:
23 | Endpoint* endpoint_;
24 | IListener* listener_;
25 |
26 | mutable Lock lock_;
27 | mutable LONG ref_count_;
28 | };
29 | }
--------------------------------------------------------------------------------
/ipc_dll/ipc_factory_impl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ipc_factory_impl.h"
3 |
4 | namespace IPC
5 | {
6 | FactoryImpl::FactoryImpl()
7 | {
8 |
9 | }
10 |
11 | FactoryImpl::~FactoryImpl()
12 | {
13 | for (auto iter : endpoint_map_)
14 | {
15 | iter.second->Release();
16 | }
17 | }
18 |
19 |
20 | IEndpoint* FactoryImpl::GetEndPoint(const char* name, IListener* listener)
21 | {
22 | if (name == NULL)
23 | return NULL;
24 | auto iter = endpoint_map_.find(name);
25 | if (iter != endpoint_map_.end())
26 | return iter->second;
27 | EndpointImpl* p = new EndpointImpl(name, listener);
28 | p->AddRef();
29 | endpoint_map_[name] = p;
30 | return p;
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/ipc_dll/ipc_factory_impl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ipc/ipc_interface.h"
3 | #include "ipc_endpoint_impl.h"
4 | #include
5 |
6 | namespace IPC
7 | {
8 | class FactoryImpl
9 | {
10 | public:
11 | FactoryImpl();
12 | ~FactoryImpl();
13 | IEndpoint* GetEndPoint(const char* name, IListener* listener);
14 | private:
15 | std::unordered_map endpoint_map_;
16 | };
17 | }
--------------------------------------------------------------------------------
/ipc_dll/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // ipc_dll.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/ipc_dll/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
11 | // Windows Header Files:
12 | #include
13 |
14 |
15 |
16 | // TODO: reference additional headers your program requires here
17 |
--------------------------------------------------------------------------------
/ipc_dll/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/sample/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | CONSOLE APPLICATION : sample Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this sample application for you.
6 |
7 | This file contains a summary of what you will find in each of the files that
8 | make up your sample application.
9 |
10 |
11 | sample.vcxproj
12 | This is the main project file for VC++ projects generated using an Application Wizard.
13 | It contains information about the version of Visual C++ that generated the file, and
14 | information about the platforms, configurations, and project features selected with the
15 | Application Wizard.
16 |
17 | sample.vcxproj.filters
18 | This is the filters file for VC++ projects generated using an Application Wizard.
19 | It contains information about the association between the files in your project
20 | and the filters. This association is used in the IDE to show grouping of files with
21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
22 | "Source Files" filter).
23 |
24 | sample.cpp
25 | This is the main application source file.
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | Other standard files:
29 |
30 | StdAfx.h, StdAfx.cpp
31 | These files are used to build a precompiled header (PCH) file
32 | named sample.pch and a precompiled types file named StdAfx.obj.
33 |
34 | /////////////////////////////////////////////////////////////////////////////
35 | Other notes:
36 |
37 | AppWizard uses "TODO:" comments to indicate parts of the source code you
38 | should add to or customize.
39 |
40 | /////////////////////////////////////////////////////////////////////////////
41 |
--------------------------------------------------------------------------------
/sample/common.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "common.h"
3 |
4 |
5 | const char kChannelName[] = "SampleServer";
--------------------------------------------------------------------------------
/sample/common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | extern const char kChannelName[];
--------------------------------------------------------------------------------
/sample/sample_client.cpp:
--------------------------------------------------------------------------------
1 | // sample.cpp : Defines the entry point for the console application.
2 | //
3 |
4 | #include "stdafx.h"
5 |
6 | #include "sample_client.h"
7 | #include "ipc/ipc_message.h"
8 |
9 |
10 | int _tmain(int argc, _TCHAR* argv[])
11 | {
12 | SampleClient listener;
13 | IPC::Endpoint endpoint(kChannelName, &listener);
14 | std::string cmd;
15 | while (true)
16 | {
17 | std::cout << ">>";
18 | std::cin >> cmd;
19 | if (cmd == "exit")
20 | {
21 | break;
22 | }
23 | else
24 | {
25 | scoped_refptr m(new IPC::Message(GetCurrentProcessId(), 0, (IPC::Message::PriorityValue)0));
26 | m->WriteString(cmd);
27 | //std::cout << "Process [" << GetCurrentProcessId() << "]: " << cmd << std::endl;
28 | endpoint.Send(m.get());
29 | }
30 | }
31 |
32 | return 0;
33 | }
34 |
35 |
36 | void SampleClient::OnChannelError()
37 | {
38 | std::cout << "Process [" << id_ << "] Disconnected" << std::endl;
39 | }
40 |
41 | void SampleClient::OnChannelConnected(int32 peer_pid)
42 | {
43 | id_ = peer_pid;
44 | std::cout << "Process [" << peer_pid << "] Connected" << std::endl;
45 | }
46 |
47 | bool SampleClient::OnMessageReceived(IPC::Message* msg)
48 | {
49 | std::string s;
50 | msg->routing_id();
51 | IPC::MessageReader reader(msg);
52 | reader.ReadString(&s);
53 | std::cout << "Process [" << id_ << "]: " << s << std::endl;
54 | return true;
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/sample/sample_client.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ipc/ipc_endpoint.h"
4 |
5 | #include "common.h"
6 |
7 | #include
8 | #include
9 |
10 | class SampleClient : public IPC::Listener
11 | {
12 | public:
13 | virtual bool OnMessageReceived(IPC::Message* msg);
14 |
15 | virtual void OnChannelConnected(int32 peer_pid);
16 |
17 | virtual void OnChannelError();
18 | protected:
19 | int32 id_;
20 | };
21 |
--------------------------------------------------------------------------------
/sample/sample_client.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {ADD3A329-4FB0-4B04-8C47-98DBFE5A06D4}
15 | Win32Proj
16 | sample
17 |
18 |
19 |
20 | Application
21 | true
22 | v120_xp
23 | Unicode
24 |
25 |
26 | Application
27 | false
28 | v120_xp
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 | ..\output\$(Configuration)\
45 | ..\build\$(ProjectName)\$(Configuration)\
46 |
47 |
48 | false
49 | ..\output\$(Configuration)\
50 | ..\build\$(ProjectName)\$(Configuration)\
51 |
52 |
53 |
54 | Use
55 | Level3
56 | Disabled
57 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
58 | true
59 | $(ProjectDir)..;%(AdditionalIncludeDirectories)
60 |
61 |
62 | Console
63 | true
64 |
65 |
66 |
67 |
68 | Level3
69 | Use
70 | MaxSpeed
71 | true
72 | true
73 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
74 | true
75 | $(ProjectDir)..;%(AdditionalIncludeDirectories)
76 |
77 |
78 | Console
79 | true
80 | true
81 | true
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Create
98 | Create
99 |
100 |
101 |
102 |
103 | {896c53b4-9517-429a-911c-1a2b634b8319}
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/sample/sample_client.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 |
35 |
36 | Source Files
37 |
38 |
39 | Source Files
40 |
41 |
42 | Source Files
43 |
44 |
45 |
--------------------------------------------------------------------------------
/sample/sample_dll_client.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | #include "sample_dll_client.h"
4 |
5 |
6 | void SampleDllClient::OnDestDisconnected()
7 | {
8 | std::cout << "Process [" << id_ << "] Disconnected" << std::endl;
9 | }
10 |
11 | void SampleDllClient::OnDestConnected(int peer_pid)
12 | {
13 | id_ = peer_pid;
14 | std::cout << "Process [" << peer_pid << "] Connected" << std::endl;
15 | }
16 |
17 | void SampleDllClient::OnMessageReceived(const char* message, size_t len)
18 | {
19 | std::string s(message, len);
20 | std::cout << "Process [" << id_ << "]: " << s << std::endl;
21 | }
22 |
23 | void SampleDllClient::AddRef() const
24 | {
25 | InterlockedIncrement(&ref_count_);
26 | }
27 |
28 | void SampleDllClient::Release() const
29 | {
30 | if (InterlockedDecrement(&ref_count_) == 0)
31 | {
32 | delete this;
33 | }
34 | }
35 |
36 | SampleDllClient::SampleDllClient()
37 | : ref_count_(0)
38 | , id_(0)
39 | , module_(NULL)
40 | , endpoint_(NULL)
41 | {
42 | Init();
43 | }
44 |
45 |
46 | SampleDllClient::~SampleDllClient()
47 | {
48 | if (endpoint_)
49 | {
50 | endpoint_->Release();
51 | endpoint_ = NULL;
52 | }
53 | if (module_)
54 | {
55 | FreeLibrary(module_);
56 | module_ = NULL;
57 | }
58 | }
59 |
60 |
61 | void SampleDllClient::Send(const std::string& cmd)
62 | {
63 | if (endpoint_)
64 | endpoint_->Send(cmd.c_str(), cmd.size());
65 | }
66 |
67 | void SampleDllClient::Init()
68 | {
69 | module_ = LoadLibrary(L"ipc_dll.dll");
70 | if (module_ == NULL)
71 | return;
72 |
73 | typedef bool (*FuncGetIPCEndPoint)(void** instance, const char* name, void* listener);
74 | FuncGetIPCEndPoint pfn = (FuncGetIPCEndPoint)GetProcAddress(module_, "GetIPCEndPoint");
75 | if (!pfn)
76 | return;
77 |
78 | if (pfn((void**)&endpoint_, kChannelName, this))
79 | {
80 | endpoint_->AddRef();
81 | }
82 | }
83 |
84 |
85 | int _tmain(int argc, _TCHAR* argv[])
86 | {
87 | SampleDllClient* client = new SampleDllClient;
88 | client->AddRef();
89 |
90 | std::string cmd;
91 | while (true)
92 | {
93 | std::cout << ">>";
94 | std::cin >> cmd;
95 | if (cmd == "exit")
96 | {
97 | break;
98 | }
99 | else
100 | {
101 | client->Send(cmd);
102 | }
103 | }
104 |
105 | client->Release();
106 |
107 | return 0;
108 | }
109 |
--------------------------------------------------------------------------------
/sample/sample_dll_client.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ipc/ipc_interface.h"
4 | #include "ipc/ipc_thread.h"
5 | #include "ipc/ipc_listener.h"
6 |
7 | #include "common.h"
8 |
9 | #include
10 |
11 | class SampleDllClient : public IPC::IListener
12 | {
13 | public:
14 | SampleDllClient();
15 | ~SampleDllClient();
16 |
17 | virtual void AddRef() const override;
18 |
19 | virtual void Release() const override;
20 |
21 | virtual void OnMessageReceived(const char* message, size_t len) override;
22 |
23 | virtual void OnDestConnected(int peer_pid) override;
24 |
25 | virtual void OnDestDisconnected() override;
26 |
27 | void Send(const std::string& cmd);
28 | private:
29 | void Init();
30 | int id_;
31 | mutable LONG ref_count_;
32 | IPC::IEndpoint* endpoint_;
33 | HMODULE module_;
34 | };
35 |
36 |
--------------------------------------------------------------------------------
/sample/sample_dll_client.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {F15D047E-1369-432E-91C0-03E932370D55}
15 | Win32Proj
16 | sample
17 | sample_dll_client
18 |
19 |
20 |
21 | Application
22 | true
23 | v120_xp
24 | Unicode
25 |
26 |
27 | Application
28 | false
29 | v120_xp
30 | true
31 | Unicode
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 | ..\output\$(Configuration)\
46 | ..\build\$(ProjectName)\$(Configuration)\
47 |
48 |
49 | false
50 | ..\output\$(Configuration)\
51 | ..\build\$(ProjectName)\$(Configuration)\
52 |
53 |
54 |
55 | Use
56 | Level3
57 | Disabled
58 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
59 | true
60 | $(ProjectDir)..;%(AdditionalIncludeDirectories)
61 |
62 |
63 | Console
64 | true
65 |
66 |
67 |
68 |
69 | Level3
70 | Use
71 | MaxSpeed
72 | true
73 | true
74 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
75 | true
76 | $(ProjectDir)..;%(AdditionalIncludeDirectories)
77 |
78 |
79 | Console
80 | true
81 | true
82 | true
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | Create
99 | Create
100 |
101 |
102 |
103 |
104 | {896c53b4-9517-429a-911c-1a2b634b8319}
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/sample/sample_dll_client.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/sample/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // sample.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/sample/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #define _CRT_RAND_
11 | #include
12 | #include
13 |
14 |
15 |
16 | // TODO: reference additional headers your program requires here
17 |
--------------------------------------------------------------------------------
/sample/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------