Skip to content

Commit

Permalink
Fixes server freezes sometimes and needs to be restarted (#3)
Browse files Browse the repository at this point in the history
* Server freezes sometimes and needs to be restarted (#2)

* Fix

- Handling inside mitmproxy's code the file descriptors limit to fix this issue

* Bridge

- Adding heartbeat to cleanup old connections

* App

- Removing old bridge and websocket's python code
- Embedding mitmdump binary with mockingbird bridge
- Improved process execution layer,

* Server freezes sometimes and needs to be restarted (#2)

* Fix

- Handling inside mitmproxy's code the file descriptors limit to fix this issue

* Bridge

- Adding heartbeat to cleanup old connections

* App

- Removing old bridge and websocket's python code
- Embedding mitmdump binary with mockingbird bridge
- Improved process execution layer,

* Server freezes sometimes and needs to be restarted (#2)

* Fix

- Handling inside mitmproxy's code the file descriptors limit to fix this issue

* Bridge

- Adding heartbeat to cleanup old connections

* App

- Removing old bridge and websocket's python code
- Embedding mitmdump binary with mockingbird bridge
- Improved process execution layer,
  • Loading branch information
erickjung authored Nov 17, 2020
1 parent 9d8cfc5 commit 8451095
Show file tree
Hide file tree
Showing 19 changed files with 285 additions and 120 deletions.
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,6 @@ Mockingbird was designed to simplify software testing, by easily mocking any sys

## Installation

### Requeriments

In order to use this tool you need MITMProxy installed through Homebrew.

1. Install [MITMProxy](https://mitmproxy.org/) if you don't already have it.

```
brew install mitmproxy
```

### Binary downloads

Oficial binaries can be found on [Release Page](https://github.com/Farfetch/mockingbird/releases)
Expand Down
Binary file added bridge/mockingbird.py.zip
Binary file not shown.
24 changes: 12 additions & 12 deletions src/Mockingbird.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
B6420D88245B375D0048131C /* data01.json in Resources */ = {isa = PBXBuildFile; fileRef = B6420D82245B375D0048131C /* data01.json */; };
B6420D89245B375D0048131C /* test02.json in Resources */ = {isa = PBXBuildFile; fileRef = B6420D84245B375D0048131C /* test02.json */; };
B6420D8A245B375D0048131C /* test01.json in Resources */ = {isa = PBXBuildFile; fileRef = B6420D85245B375D0048131C /* test01.json */; };
B652677225619054000B1E34 /* ProcessTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = B652677125619054000B1E34 /* ProcessTask.swift */; };
B652677A25619D8A000B1E34 /* mitmdump_mb.zip in Resources */ = {isa = PBXBuildFile; fileRef = B652677925619D8A000B1E34 /* mitmdump_mb.zip */; };
B65572C923D094D400D5056A /* Tracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65572C823D094D400D5056A /* Tracking.swift */; };
B6729C9C239FB0FC00CAD02D /* OptionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6729C9B239FB0FC00CAD02D /* OptionsView.swift */; };
B6736ADA23981CED0040B29D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6736AD923981CED0040B29D /* AppDelegate.swift */; };
Expand All @@ -46,14 +48,12 @@
B6736B3123981D320040B29D /* MTKViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6736B0E23981D320040B29D /* MTKViewController.swift */; };
B6736B452398EB570040B29D /* TestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6736B442398EB570040B29D /* TestView.swift */; };
B6736B5D239923230040B29D /* proxy_off.sh in Resources */ = {isa = PBXBuildFile; fileRef = B6736B58239923230040B29D /* proxy_off.sh */; };
B6736B5E239923230040B29D /* mitm_on.sh in Resources */ = {isa = PBXBuildFile; fileRef = B6736B59239923230040B29D /* mitm_on.sh */; };
B6736B5F239923230040B29D /* ip_info.sh in Resources */ = {isa = PBXBuildFile; fileRef = B6736B5A239923230040B29D /* ip_info.sh */; };
B6736B60239923230040B29D /* mitm_off.sh in Resources */ = {isa = PBXBuildFile; fileRef = B6736B5B239923230040B29D /* mitm_off.sh */; };
B6736B61239923230040B29D /* proxy_on.sh in Resources */ = {isa = PBXBuildFile; fileRef = B6736B5C239923230040B29D /* proxy_on.sh */; };
B683949B23F1CFC600882648 /* Default.swift in Sources */ = {isa = PBXBuildFile; fileRef = B683949A23F1CFC600882648 /* Default.swift */; };
B683949D23F200F800882648 /* RecordGroupInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B683949C23F200F800882648 /* RecordGroupInfo.swift */; };
B68F436C23CF5BD900D4B69C /* proxy_wifi_on.sh in Resources */ = {isa = PBXBuildFile; fileRef = B68F436B23CF5BD900D4B69C /* proxy_wifi_on.sh */; };
B694180F24115D4200A1D5F6 /* mitm_script.zip in Resources */ = {isa = PBXBuildFile; fileRef = B694180E24115D4200A1D5F6 /* mitm_script.zip */; };
B69F019323ED996F005C8B26 /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69F019223ED996F005C8B26 /* AppStore.swift */; };
B69F019623ED99AF005C8B26 /* ServerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69F019523ED99AF005C8B26 /* ServerStore.swift */; };
B69F019823ED99F8005C8B26 /* ServerReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69F019723ED99F8005C8B26 /* ServerReducer.swift */; };
Expand Down Expand Up @@ -145,6 +145,8 @@
B6420D84245B375D0048131C /* test02.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test02.json; sourceTree = "<group>"; };
B6420D85245B375D0048131C /* test01.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test01.json; sourceTree = "<group>"; };
B6420D8B245B3B1E0048131C /* Files.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Files.framework; path = Carthage/Build/Mac/Files.framework; sourceTree = "<group>"; };
B652677125619054000B1E34 /* ProcessTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessTask.swift; sourceTree = "<group>"; };
B652677925619D8A000B1E34 /* mitmdump_mb.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = mitmdump_mb.zip; sourceTree = "<group>"; };
B65572B123D0919600D5056A /* AppCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenter.framework; path = Carthage/Build/Mac/AppCenter.framework; sourceTree = "<group>"; };
B65572B223D0919600D5056A /* AppCenterAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenterAnalytics.framework; path = Carthage/Build/Mac/AppCenterAnalytics.framework; sourceTree = "<group>"; };
B65572B323D0919600D5056A /* AppCenterCrashes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppCenterCrashes.framework; path = Carthage/Build/Mac/AppCenterCrashes.framework; sourceTree = "<group>"; };
Expand Down Expand Up @@ -173,7 +175,6 @@
B6736B4123981D720040B29D /* Swifter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Swifter.framework; path = Carthage/Build/Mac/Swifter.framework; sourceTree = "<group>"; };
B6736B442398EB570040B29D /* TestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestView.swift; sourceTree = "<group>"; };
B6736B58239923230040B29D /* proxy_off.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = proxy_off.sh; sourceTree = "<group>"; };
B6736B59239923230040B29D /* mitm_on.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = mitm_on.sh; sourceTree = "<group>"; };
B6736B5A239923230040B29D /* ip_info.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ip_info.sh; sourceTree = "<group>"; };
B6736B5B239923230040B29D /* mitm_off.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = mitm_off.sh; sourceTree = "<group>"; };
B6736B5C239923230040B29D /* proxy_on.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = proxy_on.sh; sourceTree = "<group>"; };
Expand All @@ -182,7 +183,6 @@
B683949A23F1CFC600882648 /* Default.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Default.swift; sourceTree = "<group>"; };
B683949C23F200F800882648 /* RecordGroupInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordGroupInfo.swift; sourceTree = "<group>"; };
B68F436B23CF5BD900D4B69C /* proxy_wifi_on.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = proxy_wifi_on.sh; sourceTree = "<group>"; };
B694180E24115D4200A1D5F6 /* mitm_script.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = mitm_script.zip; sourceTree = "<group>"; };
B69F019223ED996F005C8B26 /* AppStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = "<group>"; };
B69F019523ED99AF005C8B26 /* ServerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerStore.swift; sourceTree = "<group>"; };
B69F019723ED99F8005C8B26 /* ServerReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerReducer.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -499,7 +499,6 @@
children = (
B6736B5A239923230040B29D /* ip_info.sh */,
B6736B5B239923230040B29D /* mitm_off.sh */,
B6736B59239923230040B29D /* mitm_on.sh */,
B6736B58239923230040B29D /* proxy_off.sh */,
B6736B5C239923230040B29D /* proxy_on.sh */,
B68F436B23CF5BD900D4B69C /* proxy_wifi_on.sh */,
Expand Down Expand Up @@ -595,9 +594,9 @@
B69F01C623EE287E005C8B26 /* Resources */ = {
isa = PBXGroup;
children = (
B652677925619D8A000B1E34 /* mitmdump_mb.zip */,
B6736AE923981D310040B29D /* Assets.xcassets */,
B6736AE323981CEF0040B29D /* mockingbird.entitlements */,
B694180E24115D4200A1D5F6 /* mitm_script.zip */,
B6736B57239923230040B29D /* Scripts */,
);
path = Resources;
Expand All @@ -618,6 +617,7 @@
isa = PBXGroup;
children = (
B69F01D323EE2EBC005C8B26 /* ProcessManager.swift */,
B652677125619054000B1E34 /* ProcessTask.swift */,
);
path = Service;
sourceTree = "<group>";
Expand Down Expand Up @@ -796,13 +796,12 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B652677A25619D8A000B1E34 /* mitmdump_mb.zip in Resources */,
B68F436C23CF5BD900D4B69C /* proxy_wifi_on.sh in Resources */,
B6736B1523981D320040B29D /* Assets.xcassets in Resources */,
B6736B3023981D320040B29D /* Main.storyboard in Resources */,
B6736B60239923230040B29D /* mitm_off.sh in Resources */,
B6736AE123981CEF0040B29D /* Main.storyboard in Resources */,
B6736B5E239923230040B29D /* mitm_on.sh in Resources */,
B694180F24115D4200A1D5F6 /* mitm_script.zip in Resources */,
B6736B61239923230040B29D /* proxy_on.sh in Resources */,
B6736B5D239923230040B29D /* proxy_off.sh in Resources */,
B6736B5F239923230040B29D /* ip_info.sh in Resources */,
Expand Down Expand Up @@ -986,6 +985,7 @@
B6736B452398EB570040B29D /* TestView.swift in Sources */,
B69F01CD23EE2CEE005C8B26 /* TaskReducer.swift in Sources */,
B69F01CF23EE2CF7005C8B26 /* TaskStore.swift in Sources */,
B652677225619054000B1E34 /* ProcessTask.swift in Sources */,
B69F01D423EE2EBC005C8B26 /* ProcessManager.swift in Sources */,
B6F4DED323EF5195003FB2C9 /* Components.swift in Sources */,
B6F89CC423F192AC008106F9 /* RecordInfo.swift in Sources */,
Expand Down Expand Up @@ -1284,7 +1284,7 @@
CODE_SIGN_ENTITLEMENTS = Mockingbird/Resources/mockingbird.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -1297,7 +1297,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.farfetch.mockingbird;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -1313,7 +1313,7 @@
CODE_SIGN_ENTITLEMENTS = Mockingbird/Resources/mockingbird.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -1326,7 +1326,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.farfetch.mockingbird;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
2 changes: 0 additions & 2 deletions src/Mockingbird/Resources/Scripts/mitm_on.sh

This file was deleted.

Binary file removed src/Mockingbird/Resources/mitm_script.zip
Binary file not shown.
Binary file added src/Mockingbird/Resources/mitmdump_mb.zip
Binary file not shown.
4 changes: 2 additions & 2 deletions src/Mockingbird/Store/AppStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import Foundation
import ReSwift

private let logging: Middleware<StateType> = { dispatch, getState in
private let logging: Middleware<StateType> = { _, _ in
return { next in
return { action in

#if DEBUG
_log(type: .info, log: "\(action)")
_log(type: .debug, log: "\(action)")
#endif

return next(action)
Expand Down
1 change: 1 addition & 0 deletions src/Mockingbird/Store/Server/ServerActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ enum ServerAction: Action {
case initialize
case start
case stop
case processed
case setCurrent(capture: ServerCapture?)
case addCapture(capture: ServerCapture)
case clearCapture
Expand Down
6 changes: 6 additions & 0 deletions src/Mockingbird/Store/Server/ServerReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ class ServerReducer {
case .start:

state.isRunning = true
state.isProcessingCommand = true

case .stop:

state.isRunning = false
state.isProcessingCommand = true

case .processed:

state.isProcessingCommand = false

case .setCurrent(let capture):

Expand Down
1 change: 1 addition & 0 deletions src/Mockingbird/Store/Server/ServerStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct ServerState: StateType {
var filter: String = ""

var isRunning: Bool = false
var isProcessingCommand: Bool = false

// UI states
var isRequestSelected: Bool = true
Expand Down
114 changes: 41 additions & 73 deletions src/Mockingbird/Store/Task/Service/ProcessManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,111 +8,79 @@

import Foundation

struct ProcessObject {
final class ProcessManager {

let type: ProcessType
let script: String
let ignoreReturn: Bool
}
static let shared = ProcessManager()

enum ProcessType {
private var mitmProcess: Process?

case proxyOn
case proxyWifiOn
case proxyOff
case mitmOn
case mitmOff
case ipInfo
func execute(process: ProcessType) {

var command: ProcessObject {
switch process {

switch self {
case .mitmOn:

case .proxyOn: return ProcessObject(type: self, script: "proxy_on", ignoreReturn: true)
case .proxyWifiOn: return ProcessObject(type: self, script: "proxy_wifi_on", ignoreReturn: true)
case .proxyOff: return ProcessObject(type: self, script: "proxy_off", ignoreReturn: true)
case .mitmOn: return ProcessObject(type: self, script: "mitm_on", ignoreReturn: false)
case .mitmOff: return ProcessObject(type: self, script: "mitm_off", ignoreReturn: true)
case .ipInfo: return ProcessObject(type: self, script: "ip_info", ignoreReturn: false)
}
}
}
ProcessTask.runAsync(process: process, callback: self)

final class ProcessManager {
case .ipInfo:

static let shared = ProcessManager()
ProcessTask.launchSync(process: process, callback: self)

func execute(process: ProcessType) {
default:

self.executeInternal(process: process)
ProcessTask.launchAsync(process: process, callback: self)
}
}
}

private extension ProcessManager {
extension ProcessManager: ProcessTaskCallback {

@discardableResult
func executeProcess(launch: String, arg: [String]?) -> Pipe {
func processStarted(_ process: ProcessType) {

let process = Process()
process.launchPath = launch
_log(type: .debug, log: "started: \(process)")
}

if let arg = arg {
func stdoutUpdated(_ process: ProcessType, text: String) {

process.arguments = arg
}
_log(type: .debug, log: "stdout: \(text)")

let outPipe = Pipe()
let errorPipe = Pipe()
process.standardOutput = outPipe
process.standardError = errorPipe
process.launch()
switch process {

let error = errorPipe.fileHandleForReading.readDataToEndOfFile()
if let errorText = String(data: error, encoding: .utf8),
!errorText.isEmpty {
case .mitmOn:
AppStore.server.dispatch(ServerAction.processed)

_log(type: .error, log: "Task Error: \(errorText)")
}
case .ipInfo:
AppStore.task.dispatch(TaskAction.updateIpInfo(info: text))

return outPipe
default:
break
}
}

func executeInternal(process: ProcessType) {

DispatchQueue.global(qos: .background).async {
func stderrUpdated(_ process: ProcessType, text: String) {

if process == .mitmOn,
let script = Bundle.main.path(forResource: process.command.script, ofType: "sh") {

let pipe = self.executeProcess(launch: "/bin/sh", arg: [script, Default.Folder.mitm + "/proxy.py"])
let data = pipe.fileHandleForReading.readDataToEndOfFile()

if let output = String(data: data, encoding: .utf8) {

_log(type: .error, log: "MITM Error: \(output)")
_log(type: .info, log: "stderr: \(text)")
}

AppStore.task.dispatch(TaskAction.stopMitm)
}
func processError(_ process: ProcessType, error: Error) {

} else if let script = Bundle.main.path(forResource: process.command.script, ofType: "sh") {
_log(type: .info, log: "error: \(error)")
}

let pipe = self.executeProcess(launch: "/bin/sh", arg: [script, (script as NSString).deletingLastPathComponent])
func processEnded(_ process: ProcessType) {

if !process.command.ignoreReturn {
_log(type: .debug, log: "ended: \(process)")

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
switch process {

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
case .mitmOn:
AppStore.task.dispatch(TaskAction.stopMitm)

if process == .ipInfo,
let output = output {
case .mitmOff:
AppStore.server.dispatch(ServerAction.processed)

AppStore.task.dispatch(TaskAction.updateIpInfo(info: output))
}
}
}
}
default:
break
}
}
}
Loading

0 comments on commit 8451095

Please sign in to comment.